V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
abcbuzhiming
V2EX  ›  MySQL

要是不准 Join,如何解决某些需要 Join 后查询的问题?

  •  
  •   abcbuzhiming · 2018-07-26 13:01:56 +08:00 · 12456 次点击
    这是一个创建于 2304 天前的主题,其中的信息可能已经有所发展或是发生改变。
    看不少经验分享提到 Mysql 在大数据量,大并发下,尽量不要用 Join,阿里巴巴的规范里提出 3 表以上别 Join ; 58 更激进直接禁止了 Join,但是 58 有自己的索引服务可以进行检索,我就想那些没有索引服务的,怎么解决某些必须 Join 后搜索的问题,用冗余字段,且不说冗余字段有关联更新问题;你要加多少冗余字段呢,那主表不是又变大了吗,另外 1 对 1 关系加冗余字段可行,多对多关系加冗余字段是没效的啊,有没有有人有这方面的经验?
    41 条回复    2018-10-26 10:09:25 +08:00
    lk0317
        1
    lk0317  
       2018-07-26 13:09:51 +08:00
    数据库层面不能 join,不代表你不能在应用层面做 join。
    Nostalgiaaaa
        2
    Nostalgiaaaa  
       2018-07-26 13:12:59 +08:00
    说句无关的。你这个头像漏点了吧。。。
    dany813
        3
    dany813  
       2018-07-26 13:13:55 +08:00
    @Nostalgiaaaa 老哥好眼力
    nowheretogogo
        4
    nowheretogogo  
       2018-07-26 13:46:09 +08:00
    不仅是 MYSQL,很多都是建议不要用多于三个 join。
    一般都是应用层面做类似于 join 的操作。
    abcbuzhiming
        5
    abcbuzhiming  
    OP
       2018-07-26 14:27:26 +08:00
    @lk0317 给你举个例子,学生一张表,班级一张表,班级自身带有入学学年,所属学院这样的属性,我现在要根据入学学年和所属学院过滤学生,你告诉我怎么在应用层 join,要实现分页查询的
    abcbuzhiming
        6
    abcbuzhiming  
    OP
       2018-07-26 14:32:42 +08:00
    @Nostalgiaaaa 没有漏点,自己去看吧
    https://yande.re/post/show/9115
    lihongjie0209
        7
    lihongjie0209  
       2018-07-26 14:33:29 +08:00
    select * from 学生 where 班级 ID IN (select id from 班级 where 学年=... and 学院=...) limit ...
    abcbuzhiming
        8
    abcbuzhiming  
    OP
       2018-07-26 14:34:54 +08:00
    @nowheretogogo 不带搜索条件的应用层 join 很容易做到,二次查询而已,但是只要加几个 where 条件搜索 join 的表,你要怎么办
    abcbuzhiming
        9
    abcbuzhiming  
    OP
       2018-07-26 14:35:41 +08:00
    @lihongjie0209 朋友,IN 的数据比较大你怎么办,in 的数据大了效率立马降低
    lihongjie0209
        10
    lihongjie0209  
       2018-07-26 14:39:51 +08:00
    @abcbuzhiming #9 应用层 for 循环
    lihongjie0209
        11
    lihongjie0209  
       2018-07-26 14:40:27 +08:00
    @abcbuzhiming #9 话说你的班级能有多少?
    saltxy
        12
    saltxy  
       2018-07-26 14:40:56 +08:00
    可以看下 CQRS 方面的东西
    lk0317
        13
    lk0317  
       2018-07-26 14:42:41 +08:00
    @abcbuzhiming 没看懂,两次 select 会有什么问题?
    kran
        14
    kran  
       2018-07-26 14:50:57 +08:00 via iPhone
    这个例子加冗余挺合适的😄
    micean
        15
    micean  
       2018-07-26 14:58:28 +08:00
    你举得这个例子,我觉得不能把普通的传统软件的分页简单套用在分表分库这种情况吧
    abcbuzhiming
        16
    abcbuzhiming  
    OP
       2018-07-26 15:06:28 +08:00
    @lihongjie0209 for 循环?循环什么数据?
    我拿班级只是做个简单的例子,还有一种查询右表是查时间范围的,右表能有几百条记录,你用 in 摆的平吗?
    abcbuzhiming
        17
    abcbuzhiming  
    OP
       2018-07-26 15:08:09 +08:00
    @lk0317 两次查询只能用在不需要 where 的场合下,我现在问你,我现在要 where 右边,而且不止一个字段,你咋办呢,像你楼下那样先查一次,然后 in 吗?可问题是 where 得到的记录非常多你咋办?
    abcbuzhiming
        18
    abcbuzhiming  
    OP
       2018-07-26 15:09:04 +08:00
    @kran 一点都不合适的好吗,你见过报表系统要过滤十来个字段的吗
    abcbuzhiming
        19
    abcbuzhiming  
    OP
       2018-07-26 15:09:54 +08:00
    @micean 分页是硬需求,你分表分库,你最后展现在用户面前的数据还不是得分页
    kran
        20
    kran  
       2018-07-26 15:16:25 +08:00 via iPhone
    @abcbuzhiming 见过
    abcbuzhiming
        21
    abcbuzhiming  
    OP
       2018-07-26 15:18:04 +08:00
    @kran 所以你怎么做?把这十几个字段全往主表里加吗?你这表膨胀成啥样了?关联更新还麻烦的要死
    liprais
        22
    liprais  
       2018-07-26 15:18:13 +08:00
    看了半天原来 lz 是抬杠来了
    要不要禁止 join 看应用呗
    oltp 和 olap 是完全不同的应用,不可一概而论的
    galaxyyao
        23
    galaxyyao  
       2018-07-26 15:18:23 +08:00
    有用到分库分表,基本大多数情况都有数据仓库层或 ODS,用于聚合数据。可以通过中间件,做到应用无感。
    TommyLemon
        24
    TommyLemon  
       2018-07-26 15:19:24 +08:00
    大公司有实力在 应用层 优化地比 Inno DB 等 MySQL 引擎好,没这个实力还是用 JOIN 吧,
    不然 IN 后面几千几万的 id 照样性能差,甚至可能导致缓冲区溢出。
    feverzsj
        25
    feverzsj  
       2018-07-26 15:23:15 +08:00
    需要用 join 的就用,你自己的解决方案不可能比数据库内的好,而且中间层难以实现理想的事务性
    abcbuzhiming
        26
    abcbuzhiming  
    OP
       2018-07-26 15:34:44 +08:00
    @liprais 我没抬杠,但是我要找到能够解决在禁用 join 下的搜索办法
    est
        27
    est  
       2018-07-26 15:34:50 +08:00
    不管什么办法,禁止 JOIN,那就数据冗余提前 JOIN 好物化呗。空间换时间而已。
    huijiewei
        28
    huijiewei  
       2018-07-26 15:34:57 +08:00 via iPhone   ❤️ 1
    写过五年存储过程的路过

    近几年基本不手写 SQL,现在,基本和 JOIN 再见了

    如果你觉得摆脱不了 JOIN 那就用

    但是跑过来说没 JOIN 就搞不了什么的,除了说你菜还能夸你杠?
    janxin
        29
    janxin  
       2018-07-26 15:36:38 +08:00
    lz 先看应用场景,那个是 join 限制还是受限于高并发的应用场景的效率提升

    没有这种限制,怎么搞都无所谓,最多就是等着就好
    letitbesqzr
        30
    letitbesqzr  
       2018-07-26 15:44:42 +08:00
    看使用场景的,企业级开发里,动不动上千张表,要展现一个表格,要让你从十多个表里关联处理,这种情况不用 join 折腾死你。

    互联网业务,要求高迸发情况下,在设计的时候就考虑好数据沉淀,尽量就不要去使用 join,对分库分表也更友好。
    xomix
        31
    xomix  
       2018-07-26 16:04:56 +08:00   ❤️ 1
    如果非要多表联合查询可用中间临时表,按照你说的班级对应学号再对应学生信息的例子来说吧。
    第一步用班级表找到学号集合写入临时表,第二部用学号集合临时表 join 学生表查到学生 id 集合写到临时表,最后用学生 id 集合查找学生信息,生成需要的输出表。

    这样比三次 join 会快很多,为什么自己看查询分析器。
    saulshao
        32
    saulshao  
       2018-07-26 17:15:27 +08:00
    我其实也有类似于楼主的困惑。
    按照数据库设计的原则,应该是表越多越好。
    如果真的不让 JOIN,对于中间层编码的负担其实是蛮大的。我能想到的办法就是 @xomix 的回帖,只是不用临时表,直接读到内存里,分批循环.......但是我觉得这其实很难保证可靠。所以其实临时表是更快更好的办法。
    zjsxwc
        33
    zjsxwc  
       2018-07-26 17:24:11 +08:00
    加冗余字段

    使用应用层代码多次查询


    编不下去了,表多了用 join 不是很正常的需求吗?笛卡尔积的导致效率问题,不可避免,解决方案无非是内存空间换时间
    rockyou12
        34
    rockyou12  
       2018-07-26 18:02:49 +08:00
    不 join 其实还挺正常的……真的业务量大了基本瓶颈都在数据库,然后数据库扩容又特别麻烦,但是缓存却比较容易。你都是手写 sql,然后一堆 join,怎么搞应用层的缓存?
    mandy0119
        35
    mandy0119  
       2018-07-26 19:24:50 +08:00
    很简单的问题啊。按你举得例子,先应用层查一下班级表,把复合要求的学生 id 存一个 list,再将 list 的数据遍历逐个查学生表就行了。我们这边从来不怕应用层繁琐,互联网项目把压力拦截在应用层,通过内存进行优化,打死不透到数据库是常识吧。
    CRVV
        36
    CRVV  
       2018-07-26 20:15:25 +08:00   ❤️ 1
    这根本不是 JOIN 的问题

    按照关系型数据库的范式来设计表,不加缓存,JOIN 必然是最快的方法
    如果有其它的方法比 JOIN 快,那是数据库太蠢了

    如果用这种方式还不够快,那解决的方法当然多得很
    比如你可以不用关系型数据库

    另外,这类问题的重点是不要把代价大的事情放到关系型数据库里去做。
    不用 JOIN 的 SQL 可以代价很大,JOIN 100 个表也可以代价很小。
    阿里巴巴规定 3 个表不能 JOIN,这说明他家工程师水平比较烂,没有能力判断一个 SQL 的代价是不是太大,适不适合放到数据库去查询,仅此而已。
    Infernalzero
        37
    Infernalzero  
       2018-07-26 22:02:16 +08:00
    冗余字段是一种方式,牺牲些一致性
    还有种方式就是通过数据同步创建新的宽表来查询,这里可以接搜索,也可以直接查
    bringyou
        38
    bringyou  
       2018-07-26 23:48:31 +08:00
    跟一个前阿里云的哥们聊过,听说他们是不让用 join 的,统一上 opensearch.
    但是对普通公司来说所有表都上 opensearch 成本难以接受吧
    ryuzaki113
        39
    ryuzaki113  
       2018-07-27 09:30:54 +08:00
    不做统计还是别 join 了
    glacer
        40
    glacer  
       2018-08-04 00:52:59 +08:00
    强制规定 JOIN 表的数量也只是部分大公司出台的规定,这也是他们的无奈之举,在开发水平参差不齐的情况下这是保证系统鲁棒性最有效的办法。并不是说多表 JOIN 一定会造成性能问题,只要索引得当,多表 JOIN 一样很快,这本身就是关系型数据库的优势所在。
    wangws
        41
    wangws  
       2018-10-26 10:09:25 +08:00
    表大了,做冗余很正常,但是城市、区、县、省这种,不用 Join 真的非常麻烦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1007 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 22:36 · PVG 06:36 · LAX 14:36 · JFK 17:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.