V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hackingwu
V2EX  ›  程序员

我们公司不让开发使用 join 包括 left join,不让用子查询,合理吗?

  •  3
     
  •   hackingwu ·
    hackingwu · 2020-06-03 16:47:10 +08:00 · 32133 次点击
    这是一个创建于 1632 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我们公司规范不让开发使用 join 包括 left join,也不让用子查询,原因是为了减轻 DB 的压力,这样就导致我们一个多表联合查询的业务就要拆分多条语句,导致无效的请求和数据传输。我们业务是微服务架构。 我觉得是很不合理的。减轻了 DB parse 的压力,却带来了处理请求和数据传输的压力。 大家觉得呢?是我错了吗?

    231 条回复    2023-11-09 09:38:17 +08:00
    1  2  3  
    encro
        101
    encro  
       2020-06-04 09:19:59 +08:00
    不用 JOIN 和子查询,你用什么 SQL,KV 最适合你。

    连 SQL 都不敢用,还能指望用好其他的数据库?

    不是让开发人员学习掌握如何用好 SQL,而是野蛮不让用,这样的团队能成长?

    楼上一堆说数据库不好扩展的,请问主从会了不?数据库里面有几亿数据了没?

    搞程序的人云即云害死人。
    sdwgyzyxy
        102
    sdwgyzyxy  
       2020-06-04 09:26:02 +08:00
    出于微服务的考虑,join 查询的确不太允许,除非将来按业务拆分数据库,你能保证你 join 的所有表都会被分在同一个数据库中,要不还是理解下 DBA 的苦衷,我们就经历过一次服务拆分,真的很恶心,拆分完各业务独立数据库,独立升级部署都很方便.
    houshengzi
        103
    houshengzi  
       2020-06-04 09:32:02 +08:00
    曾经试过两张百万表不用 join,那个业务代码逻辑写多了很多

    最终还是要看具体的业务逻辑吧,一句就否掉 join 是不对的
    syyy
        104
    syyy  
       2020-06-04 09:37:20 +08:00
    减轻了 DB parse 的压力,却带来了处理请求和数据传输的压力。
    这个想法是怎么来的呢?
    lichao
        105
    lichao  
       2020-06-04 09:42:29 +08:00
    @syyy 处理请求可以水平扩展,DB 则不能
    lichao
        106
    lichao  
       2020-06-04 09:42:45 +08:00
    @syyy 或很难
    collery
        107
    collery  
       2020-06-04 09:49:16 +08:00   ❤️ 2
    看来 v2 大多数都没到分库分表的阶段。
    uoryon
        108
    uoryon  
       2020-06-04 09:58:11 +08:00
    提供一个额外的思路吧。(浅见,也没写过什么很大的这种在线系统
    这种情况还是分场景讨论,如果只是普通的系统,记录条数比较小的情况下,那你该用用。但是当量起来了,就得从另外一个层面来考虑。

    假设一直在用 join,不考虑存储,当量起来了,一些计算操作会开始膨胀,机器 cpu 会加得非常多,那怎么办,mysql 水平扩展还是垂直扩展,垂直扩展,上更好的机器,水平扩展,将 mysql 做成集群的。请求更大,集群变得更大?这两种都比较难受,垂直扩展的话,不可能有更大的机器让你不停的换,水平扩展的话,存储也水平,扩展,同时 mysql 这种是有状态的服务,运维压力更大了。

    那有一个比较简单的方式,降低 mysql cpu 消耗,就是让 mysql 只做存储的事情(上面各位大佬说的当 kv ),业务计算逻辑放到后端来做,这样计算量起来,只用水平扩展后端服务就好了,挂在 lb 后面的服务随便扩容缩容。运维成本会小很多。当 mysql 还是不够的话,就开始上分库分表了。
    tiedan
        109
    tiedan  
       2020-06-04 10:03:50 +08:00
    可以拍着胸脯说,出了问题我担着。看看他给不给用
    neptuno
        110
    neptuno  
       2020-06-04 10:05:30 +08:00
    为了以后分表分库考虑?还是只是做决定的人看了网上的文章,一拍脑袋说的
    nekoyaki
        111
    nekoyaki  
       2020-06-04 10:10:43 +08:00
    我觉得是这样,如果你能自己想出理由说服领导(或者哪怕是说服网友),比如用的好处和坏处都有什么,那你就可以用。
    如果你自己都不知道为什么不让你用,那么不让你用就是合理的。
    bnm965321
        112
    bnm965321  
       2020-06-04 10:14:22 +08:00
    @love 而且网络 IO 慢得多
    jsjjdzg
        113
    jsjjdzg  
       2020-06-04 10:39:32 +08:00
    合理啊,DB 压力要降到最低的
    dawniii
        114
    dawniii  
       2020-06-04 10:42:32 +08:00
    请教下楼上的大佬不用 join 怎么实现以下需求?用关系型数据库存文章,每篇文章包含多个标签(一对多),每篇文章包含多个作者(一对多),后台管理页面需要按作者和标签检索并分页。
    magicnian
        115
    magicnian  
       2020-06-04 10:42:38 +08:00
    你如果经历过 db 挂了导致的事故就理解 dba 的苦衷了,按照微服务的设计思想,确实不应该多表联查,但是这是建立在非常大数据量的前提下,像我公司,业务数据都快百亿了,这时候再关联表查,db 妥妥的挂
    magicnian
        116
    magicnian  
       2020-06-04 10:43:34 +08:00
    @dawniii 为什么不考虑用 nosql?如果你数据量小当我没说
    dcoder
        117
    dcoder  
       2020-06-04 10:46:10 +08:00   ❤️ 2
    推荐用 join 的确实都是小白
    leo8
        118
    leo8  
       2020-06-04 11:09:23 +08:00 via iPhone
    @yukiloh 可以
    dawniii
        119
    dawniii  
       2020-06-04 11:09:42 +08:00
    @magicnian 这种关联关系挺常见的,所以最终归宿都是 nosql ?
    woshifyz
        120
    woshifyz  
       2020-06-04 11:15:39 +08:00
    小白太多了,估计让小白写 join 也写不对吧。。。
    magicnian
        121
    magicnian  
       2020-06-04 11:16:53 +08:00
    @dawniii 这么跟你说吧,你可以用关系型数据库去存小字段数据,大字段数据推荐放 nosql 中,比如 mongodb 。只是拿 nosql 作为存储工具。当然,现在像 mysql 已经非常给力了,8.0 版本后性能有了质的飞跃,你数据量小,用 mysql 随便怎么玩都行
    magicnian
        122
    magicnian  
       2020-06-04 11:20:19 +08:00
    @dawniii 我指的数据量小是在几十亿量级的,用 mysql 抗的住,即使不用分库分表,前提是对表设计要求非常严格,比说楼主提的,绝不允许 join 查询
    zarte
        123
    zarte  
       2020-06-04 11:21:31 +08:00
    不用 join 导致的问题就是不符合数据库三范式。大表 join 确实查询会很慢(仅用过 mysql ),用程序来处理数据库压力是减轻了,是否有测过处理时 web 服务器的消耗。不 join 的前提是原本多张表的数据放同一张,程序也不需要查多张再处理。
    troywinter
        124
    troywinter  
       2020-06-04 11:22:41 +08:00
    微服务架构本来就不应该去关联不属于你的服务的表,应该用接口的方式去通信,禁止 join 的做法没有错,前天刚看到我司四个 join 的语句,explain 出来连续四五个 nested loop,如果你能为你写的 join 语句担责,愿意赔钱,那没问题,不然就老老实实遵守公司的规则。如果你觉得你司的数据量就这么小,以后也涨不了多少,那你大可以跟你老板去说,辞职吧。
    magicnian
        125
    magicnian  
       2020-06-04 11:26:30 +08:00
    @encro 我觉得重点不是 sql 不敢用这个问题,是很多开发其实用不好复杂的 sql,而且当你的业务数据达到几十亿,上百亿后,很难在 sql 上去做优化,目前就 mysql 而言,只有分库分表一条路。但是分库分表带来的成本是很高的,如果项目初期就野蛮放纵,让开发瞎写 sql,当你想做分库分表的时候就知道有多痛苦了。所以基本上,都会有类似楼主公司的一些限制,为的就是后面数据量级上来好做优化
    huijiewei
        126
    huijiewei  
       2020-06-04 11:30:01 +08:00
    @dawniii 你这个简单的不能再简单了。小系统的归类统计不值得上专门的统计系统,用用 JOIN 也就罢了,你这种简单的 3 连有什么必要用 JOIN ? 分拆成 3 个 SQL 不就完事了
    dawniii
        127
    dawniii  
       2020-06-04 11:32:06 +08:00
    @magicnian 你说的部分数据放到 mongo,如果查询字段同时有 mongo 和 mysql 的字段岂不是炸裂。我倒是觉得数据量大了,把查询的关键字段都放到 es 或者 nosql,然后用主键去 mysql 查详情就好。
    cbasil
        128
    cbasil  
       2020-06-04 11:32:38 +08:00
    多表查询不建议用 join,如果查询条件分布在多表中,用视图比较好
    dawniii
        129
    dawniii  
       2020-06-04 11:34:29 +08:00
    @huijiewei 不用 join 我是实现不了,请教下这个怎么拆成 3 个 sql 还能满足需求。
    syyy
        130
    syyy  
       2020-06-04 11:56:05 +08:00
    @lichao 我只是想知道,楼主这个想法是哪里来的,不是我的想法。
    goodboy95
        131
    goodboy95  
       2020-06-04 11:58:42 +08:00
    @huijiewei 简单的 3 连可还行,你拆分出来的 3 个 sql 不会把整张表读出来了吧,不然的话我是想不到怎么在有多表搜索条件的情况下保证分页功能正常的。
    cco
        132
    cco  
       2020-06-04 12:00:23 +08:00
    一杆子打死的- -
    goodboy95
        133
    goodboy95  
       2020-06-04 12:02:18 +08:00
    @sanggao 请解释原因
    goodboy95
        134
    goodboy95  
       2020-06-04 12:10:41 +08:00   ❤️ 1
    说真的,不让用 join 就算了,楼上还有人说一块把事务禁掉的,这还用个 x 的 mysql ?光论存取的话 mongodb 那是真比 mysql 快。
    说真的,有些情况下需求方真提个蛋疼的需求,完全可以把整个代码规范搞死。我现在做一个系统,存储人员的姓名和工号还有别的玩意,结果需求方要求可以输入员工名字 /工号的一部分(有可能是中间一部分)去搜索,这种操作别说 mysql 了,es 都是让人尽量不用的(虽然 es 的 wildcard 搜索确实比 mysql 快不少),但我能怎么办?一看人员数量,也就万把人吧,一年也不会增长 1000 个,最后也只能做了。
    huijiewei
        135
    huijiewei  
       2020-06-04 12:12:53 +08:00
    @dawniii
    @goodboy95

    你们是多小白啊,这么简单的都不会
    SELECT id FROM tag WHERE name = XXX 取出 tag id,
    SELECT id FROM user WHERE name = XXX 取出 user id

    SELECT * FROM article WHERE tag_id IN(tag_ids)
    SELECT * FROM article WHERE user_id IN(user_ids)

    有什么难点?你告诉我
    pkwenda
        136
    pkwenda  
       2020-06-04 12:29:28 +08:00   ❤️ 1
    对业务自信,这样做完全没得问题,开发也很清晰,维护别人代码也容易,另外阿里开发手册是不是也不推荐用任何 join ? 反正我们已经很久不用了
    nnnToTnnn
        137
    nnnToTnnn  
       2020-06-04 12:33:03 +08:00
    @nnd #25L 我猜楼主的技术架构中间层来进行扩展,数据库只是作为存储,不处理任何逻辑,将逻辑放在中间层,很方便跨库查询,分表分库? 估计有一套自己的事务控制,和自己的缓存控制。 所以才禁止使用 join 。
    dawniii
        138
    dawniii  
       2020-06-04 12:34:57 +08:00
    @huijiewei 你的 article 表可以 in 查询 tag_id? 这么神奇的吗?手动狗头
    nnnToTnnn
        139
    nnnToTnnn  
       2020-06-04 12:36:20 +08:00
    如果用了 join 对缓存的命中这一块,以及分库分表这一块非常难处理。 不用 join 是对缓存命中,和分库分表的妥协。
    mscb
        140
    mscb  
       2020-06-04 12:39:52 +08:00 via Android
    不能只看当前,看看未来。相比于不用 join 带来的开发效率损失,业务量上去以后进行服务拆分带来的工作量才是大成本。
    给未来留后路,我认为不是什么问题,甚至很明智。
    但如果这个业务本来也不是那种今后业务会很大的项目,比如某某内部管理系统,那有这个规定,纯属有问题
    newtype0092
        141
    newtype0092  
       2020-06-04 12:52:49 +08:00
    @dawniii 老哥你说的场景是这样的关系么?
    article(id, ...)
    tag(id, ...)
    author(id, ...)
    article_tag(id, article_id, tag_id)
    article_author(id, article_id, author_id)
    dawniii
        142
    dawniii  
       2020-06-04 12:56:08 +08:00
    @newtype0092 对,是这样的。
    hpu423
        143
    hpu423  
       2020-06-04 13:05:45 +08:00
    大流量的项目都是这么要求的吧,赞成 join 的之前开发的应该都是小项目
    qiumaoyuan
        144
    qiumaoyuan  
       2020-06-04 13:18:49 +08:00
    哈哈哈
    Narcissu5
        145
    Narcissu5  
       2020-06-04 13:26:31 +08:00
    既然你们都是人均千万级了,给我一个不用 mongo 坚持使用 mysql 的理由,新版的 mongo 也支持 ACID 了
    huijiewei
        146
    huijiewei  
       2020-06-04 13:37:26 +08:00
    @dawniii 说你菜吧。SQL 都写给你了。还是看不懂?
    huijiewei
        147
    huijiewei  
       2020-06-04 13:39:24 +08:00
    @dawniii 明白了。你是中间关联表的多对多关系吧。那再加两条就好了。

    PS: 对不起,开始没想着你用中间表关联,疏忽了
    pangleon
        148
    pangleon  
       2020-06-04 13:40:22 +08:00
    @troywinter 确实。微服务这么设计就是一个服务只能访问固定的几个表。
    如果真要跨表还是老老实实用视图或者 ES 吧
    dawniii
        149
    dawniii  
       2020-06-04 13:41:40 +08:00
    @huijiewei 哈哈哈哈哈哈,确实看不懂,可能你用的是 mysql pro max,我用了个 mysql se
    594duck
        150
    594duck  
       2020-06-04 13:43:38 +08:00
    @magicnian 几十亿,几亿行的表稍宽一点的表 MYSQL 都撑不住,我们做物流的都是上 DRDS 的百库百表方案。更不要说如果有大数据团队还要抽数据呢。
    CRVV
        151
    CRVV  
       2020-06-04 13:43:49 +08:00   ❤️ 1
    @dawniii

    这种情况不叫一对多,叫多对多。
    一对多应该把表做成这样,不需要中间表。
    article(id, ...)
    tag(id, name, article_id)
    author(id, name, article_id)

    这种全用中间表不带冗余字段的设计,是符合关系型数据库范式的表结构,在这种表结构上当然要用 JOIN 。
    不用 JOIN 的话表就不这么设计了,比如用 PostgreSQL 的 JSONB 数组来存 tag,直接放在 article 表里面,建一个 GIN 索引。

    即使是这样的表结构,不用 JOIN 当然是可以查的,只不过比用 JOIN 慢。
    SELECT id FROM tag WHERE name = XXX 取出 tag_id
    SELECT article_id FROM article_tag WHERE tag_id = xxx 取出 article_tag_ids

    SELECT id FROM user WHERE name = XXX 取出 user_id
    SELECT article_id FROM article_author WHERE author_id = xxx 取出 article_author_ids

    SELECT * FROM article WHERE id IN(article_ids1) AND id IN (article_ids2)

    但是,
    前两个 SQL 合并成 SELECT article_id FROM tag INNER JOIN article_tag ON tag_id = id WHERE name = xxx 当然会比查两次要快。因为这个 JOIN 没有带来额外的开销。我觉得即使是 MySQL 也能正确地执行这句 SQL
    后面两条也一样。

    如果全都合在一起,
    SELECT article.* FROM article
    INNER JOIN article_tag ON article.id = article_tag.article_id
    INNER JOIN tag ON tag.id = article_tag.tag_id
    INNER JOIN article_author ON article.id = article_author.article_id
    INNER JOIN author ON author.id = article_author.author_id
    WHERE tag.name = xxx AND author.name = yyy
    GROUP BY article.id

    这个 SQL 也没什么问题,JOIN 仍然没有引入额外的开销,而且还比上面那 5 句好懂。
    但如果用的数据库是 MySQL,这个 SQL 很有可能被用奇怪的方式来执行,那当然就慢了。
    这就是很多人说不能用 JOIN 的理由。
    huijiewei
        152
    huijiewei  
       2020-06-04 13:43:49 +08:00
    @dawniii 关系型数据库都实现了标准 SQL 语句,看不懂标准 SQL 语句更别谈 LEFT JOIN, RIGHT JOIN ,INNER JOIN ,OUTER JOIN 了
    594duck
        153
    594duck  
       2020-06-04 13:45:38 +08:00
    这就是强上微服务的恶果,拆的太散了,根本不方便做业务了。

    所以我说 90%的企业不适合上微服务,上 SOA 就足够了。
    neilq
        154
    neilq  
       2020-06-04 13:52:29 +08:00   ❤️ 1
    你的想法没问题。你们企业规范也没问题。
    数据库 sql 连接性能高,还是拆分查询性能高,在不同场景各有优劣。没什么好争的。
    什么大流量大数据也都是屁话,也不是一刀切不用连接的理由。大流量也不是所有业务都是大流量,都不允许用连接 ok?

    这么规范完全是为了人员素质管理考虑。企业一大啊,各种各样的人都来了,这里面呢,有些人是真的水的不行。我曾经在一家单位的时候,有个业务部的小伙子写个比较复杂的查询,数据量不多,这里连接那里嵌套写个 sql,api 执行时间 6 秒,我们小组的另一个小伙子看不下去了去优化一下变成 100 毫秒,同样的用的纯 sql 。我可以明确的说,不管你们这这里这个大流量那个分库说的头头世道,都不是主要原因。主要原因就是这样的菜逼太多太多了,为了减少这种错误的上限呢,人又多,今天来需求明天就要上线,不可能天天盯着别人屁股去优化,那就业务部门一刀切,不准用,我哪怕全部 getByIds 去组装数据,一个普通的接口也跑不出 6s 的时间,就这么回事。
    newmlp
        155
    newmlp  
       2020-06-04 13:54:14 +08:00
    看业务,如果数据库压力大,就应该把业务逻辑放到应用里处理
    dawniii
        156
    dawniii  
       2020-06-04 13:55:47 +08:00
    @CRVV 感谢老哥的回答,老哥你说的对。其实我不是很在意一对多还是多对多,就是想说用 mysql 设计成这样的关系,当查询条件涉及到多个表的字段,不用 join 就没法实现我想要的功能。而不是一刀切的不能用 join,不能用 join 的话,肯定就不会这么设计,直接用 nosql 了。
    xy2020
        157
    xy2020  
       2020-06-04 13:55:47 +08:00
    技术水平高的人认为合理,水平低的认为不合理
    开发经验丰富的人认为合理,经验欠缺的认为不合理

    至于为什么,自己琢磨吧。
    goodboy95
        158
    goodboy95  
       2020-06-04 14:05:15 +08:00
    @huijiewei ……我的回复专门把“分页”强调出来,结果你还真在这全表查呢……
    最下面两个 sql 可能会各查出几万条数据,然后在代码里一波 union,手动分页……这画面还是挺美的
    goodboy95
        159
    goodboy95  
       2020-06-04 14:05:51 +08:00
    @xy2020 有点意思哦,让你下这个结论的数据源麻烦透露一下
    goodboy95
        160
    goodboy95  
       2020-06-04 14:09:56 +08:00
    @xy2020 说真的,楼上有两个人跟你一样,在这企图用所谓“技术能力”来压人。这种话谁不会说?换我我也会,“技术水平高的要么直接上 NoSql,既然上了 Sql 就一定是需要 Sql 的特性。技术水平低的才会用 Sql 不干 Sql 事。”
    james122333
        161
    james122333  
       2020-06-04 14:10:04 +08:00
    个人也不太喜欢 sql
    效能并没有想像中那么强
    语法也反程序员
    看来有人跟我一样走大牛的路
    ljzxloaf
        162
    ljzxloaf  
       2020-06-04 14:17:19 +08:00
    OLTP 和 OLAP 要分开
    zorui
        163
    zorui  
       2020-06-04 14:18:09 +08:00   ❤️ 1
    不让使用 join 是 微服务拆分的问题吧。 不同服务下的表不让 join 合理。 同一服务下的不让 join 就说不过去了。
    pws22
        164
    pws22  
       2020-06-04 14:19:34 +08:00
    三张表 一张 文章表 一张 评论表 一张用户表
    查询 上海地区的用户 在 6.1 - 6.7 号 没有 发表过评论的用户 分页查询
    不用 join 的话 不知道逻辑咋写 大佬们能给点意见么
    liuxingdeyu
        165
    liuxingdeyu  
       2020-06-04 14:24:08 +08:00
    看业务量吧,通常来说 io 都是性能瓶颈,而解决性能的时候,最好是通过代码的手段,db 最好只是个 db,尽力不要有太多逻辑操作
    goodboy95
        166
    goodboy95  
       2020-06-04 14:33:04 +08:00
    @huijiewei 好吧,仔细想想的话,你这 3 个 sql 倒也能用,不过我是不打算一直这么搞了,啥时候真要优化了再这么干。
    realpg
        167
    realpg  
       2020-06-04 14:36:55 +08:00
    开发不给力的情况下,禁止 left join 小词典类数据表以外的 join,不算过分。


    如果开发都是特别给力的,精通数据库查询优化设计和索引,那无所谓
    dawniii
        168
    dawniii  
       2020-06-04 14:49:33 +08:00
    @CRVV 老哥,你这个表结构, [SELECT id FROM tag WHERE name = XXX 取出 tag_id] 这一句可以取出几万个 id,用这几万个 id 再去 in 查询后面的数据这不止是慢吧。
    prolic
        169
    prolic  
       2020-06-04 14:52:44 +08:00
    绝了,看了下,赞同 join 的做的是 erp 之类的企业内部系统,不赞同 join 的都是互联网做 2c 的,这玩意要具体情况具体分析啊
    msg7086
        170
    msg7086  
       2020-06-04 15:21:00 +08:00
    @hackingwu #97 数据库 Slave 可以集群,但是数据库集群是有一致性问题的,你往 Master 写数据然后回头从 Slave 读,读出来的不一定是新的值。维护一个 100 台 Slave 的集群比维护 100 台 App server 要难得多。
    msg7086
        171
    msg7086  
       2020-06-04 15:24:22 +08:00
    @dawniii #167 取几万个 ID 然后再用 IN 查询为什么会慢,兄弟能不能说说看?
    sun1991
        172
    sun1991  
       2020-06-04 15:40:54 +08:00
    @msg7086
    #167 取几万个 ID 然后再用 IN 查询为什么会慢,兄弟能不能说说看?
    -- 涉及到数据库 IO 操作底层. 有时候按照 ID 逐个读取数据 (即便走索引) 可能比全表扫描花费更多的 IO. 所以数据库层面这块是有优化的, 引擎会决定使用 IO 少的操作来读取数据.
    sun1991
        173
    sun1991  
       2020-06-04 15:43:01 +08:00
    @msg7086 Sorry, 看错了. 当我没说.
    dawniii
        174
    dawniii  
       2020-06-04 15:43:39 +08:00
    @msg7086 几万只是随便说的一个数字,如果数据量更大呢,然后要在内存里组装一个巨大的 sql 出来吗?还有和直接子查询 select xxxxxx from article where id in(select xxx)好像没啥区别,楼主说也不能用子查询。
    hackingwu
        175
    hackingwu  
    OP
       2020-06-04 15:44:47 +08:00
    @msg7086 我们的应用都是读写分离的,正常写代码的时候就会考虑可能存在延迟。
    hackingwu
        176
    hackingwu  
    OP
       2020-06-04 15:46:38 +08:00
    @zorui 这个我赞同,不同服务下不让 join 合理,考虑不同服务可能会不同的数据库。但是很多公司都是一刀切的规范
    hackingwu
        177
    hackingwu  
    OP
       2020-06-04 15:47:40 +08:00
    @sdwgyzyxy 我们其实主要讨论的是同一个服务的,即同一个库里的表 join
    hackingwu
        178
    hackingwu  
    OP
       2020-06-04 15:52:13 +08:00
    @pangleon 服务内的表 为啥不能 join
    wangyzj
        179
    wangyzj  
       2020-06-04 15:59:53 +08:00
    @hackingwu #178 其实我还是同意前面有人说的,你们公司可能没有 dba 去负责调优
    根据不同业务去设计表格结构很重要
    互联网应用会出现很多冗余的数据来避免这种复杂的查询
    说白了,因地制宜把
    这是一个成本和效率的博弈
    Michaelssss
        180
    Michaelssss  
       2020-06-04 16:05:20 +08:00
    @neilq 哈哈哈哈哈,N 个项目经理会过来赞成你的
    msg7086
        181
    msg7086  
       2020-06-04 16:07:35 +08:00
    @hackingwu #173 你说得没错,很多公司写项目是提前考虑读写分离数据延迟的。
    但是反过来看,没有提前考虑数据延迟的项目,在遇到数据库瓶颈的时候就要抓瞎了,得返工回去重新做结构。
    这种把数据库当 KV 表的做法,可以看成是缓解数据库瓶颈的「另一种」做法。

    @dawniii 所以你还是没说为什么呀。
    「然后要在内存里组装一个巨大的 sql 出来吗」
    所以就让数据库在内存里组装两个巨大的 joined dataset 出来吗?
    一个 ID 撑死也就几字节,几万个 ID 也就占用巨大的几十 KB 内存。
    几百 GB 的数据表,几十 MB 的索引,放在数据库内存里组装数据集你一点不心疼,几十 KB 反倒是那么心疼?

    「如果数据量更大呢」
    如果数据量更大,你会发现 MySQL 做 JOIN 或者子查询会更慢……

    子查询也好,JOIN 也好,能用上索引和查询缓存的情况只会比单句查询更少。如果是 Oracle 或者 Postges 这些质量比较高的数据库引擎,可能还靠谱点。如果是 MySQL,放在几年前,你查询稍稍写偏一点,或者索引建得让引擎不舒服了,立马 扫·全·表。现在其实也没好到哪里去,但是因为 MySQL 本身速度还挺快的,所以扫全表就扫全表吧,眼不见为净了。
    dawniii
        182
    dawniii  
       2020-06-04 16:14:00 +08:00
    @msg7086 正常来说几百 GB 的数据表,查出来的关联 id 才几万个?我用 join 可不是扫全表的关联关系啊。
    fyxtc
        183
    fyxtc  
       2020-06-04 16:19:47 +08:00
    @sanggao 牛逼
    whasyt
        184
    whasyt  
       2020-06-04 16:28:22 +08:00
    那就直接用 nosql 数据库吧
    cayjian
        185
    cayjian  
       2020-06-04 16:29:09 +08:00
    @prolic 赞同,脱离实际业务应用场景的讨论都是在杠,
    技术方案和规范都不是一成不变的,随着公司发展业务变化在不停地迭代,
    没有完美方案,只有当前最优解
    fansfans
        186
    fansfans  
       2020-06-04 16:36:05 +08:00
    @huijiewei 请教一下 这样如果标签数据特别多 开销是不是有点大 而且 In 查询的效率本来就不高把
    xingyuc
        187
    xingyuc  
       2020-06-04 16:37:22 +08:00
    天天想的是表里有几亿数据怎么办,哪来的数据……
    CRVV
        188
    CRVV  
       2020-06-04 16:43:34 +08:00 via Android
    @dawniii
    不让用 JOIN 的话,只能这么拆着查。
    而且我也说了用 JOIN 应该更快。

    重点其实是不用 JOIN 就不这么建表了。

    用不用 JOIN 只是不同的观点,并没有什么优劣之分,如果 JOIN 那么不堪,这些个数据库还做这个功能干啥。
    如果表是按照关系型数据库范式设计的,在上面做查询当然要用 JOIN 。不用 JOIN 有不用的玩法,从一开始就不一样。
    PostgreSQL 在 2008 年加的 hstore,2012 年加的 JSON,都是反范式的功能。在反范式的表上不用 JOIN 来查询就很正常了。
    hxy91819
        189
    hxy91819  
       2020-06-04 17:10:00 +08:00
    在互联网项目中,程序的执行效率并不是摆在第一位的,摆在第一位的应该是程序的水平扩展性和可维护性。

    该不该用 JOIN,当然不能一刀切。但是,作为新人,你觉得你比同事更加了解你们的项目吗?

    引用《高性能 MySQL 》——6.3.3-分解关联查询,总结得很全面:

    很多高性能的应用都会对关联查询进行分解,有如下的优势:
    1 、让缓存效率更高。如果某张表很少变化,那么基于该表的查询就可以重复利用查询缓存结果。
    2 、将查询分解后,执行单个查询可以减少锁的竞争。
    3 、在应用层做关联,可以更容易对数据库进行拆分,更容易做到高性能和可扩展。
    4 、查询本身效率也可能会有所提升。例如 IN()代替关联查询,可能比随机的关联更高效。
    5 、减少冗余记录得查询。
    6 、更进一步,这样做相当于在应用中实现了哈希关联,而不是使用 MySQL 得嵌套循环关联。某些场景哈希关联得效率要高很多。

    不过补充下,本书虽然很好,但是是基于 MySQL 5.5 的,现在 MySQL 已经发展了不少,对于 JOIN 的优化也多了很多。
    msg7086
        190
    msg7086  
       2020-06-04 17:29:37 +08:00
    @dawniii 几百 GB 的数据表,做过滤查询的时候只查出一部分不是很正常吗?
    如果你用 JOIN,能保证充分利用索引做高速连接,我觉得是没有问题的。
    不过这里主要讨论的是不做连接的时候性能会受到多大影响的问题。
    实际开发环境中有很多查询,在使用 JOIN 时无法充分利用索引,或者至少 MySQL 会比较笨不去用索引,这种时候做简单查询然后手动去处理,可能会比依赖数据库内部查询优化速度更快一些。毕竟查询优化并不一定能洞悉你最终的意图,并不一定能给出最佳的查询计划。

    楼上#187 里也举了很多相关的例子,提到的这些其实也就是我们上面提到的,服务器更容易扩展,更容易利用查询缓存,减少锁等等。我个人并不反对使用简单的 JOIN 查询,但是对于应用层简单而数据库层复杂的查询,我是绝对会放在应用层做的。
    fansfans
        191
    fansfans  
       2020-06-04 17:30:32 +08:00
    @goodboy95 我们公司搜索差不多 一个订单搜索十几个搜索项 基本都是模糊搜索 而且还是从不同的表中检索
    dawniii
        192
    dawniii  
       2020-06-04 17:48:03 +08:00
    @msg7086 整个帖子看下来,感觉就是三个原因不用 join 。

    1. 开发人员水平参差不齐
    2. mysql“垃圾”
    3. 业务扩展性

    都这么纠结了,是不是直接用 nosql 会更好。
    liprais
        193
    liprais  
       2020-06-04 17:51:22 +08:00
    用了 nosql 你就要开始纠结数据为啥不对了
    kalok
        194
    kalok  
       2020-06-04 17:52:30 +08:00 via Android
    一圈回覆看下來,有的老哥不知道哪裡來的想法。如果分表但不分 DB,是真的用 join 比較快。這一點在新版的 MySQL 或者 PostgreSQL 都是做過實驗的。表放在不同的 DB 上的話,就有小心考慮了。而且 many to many 的關係,一般也是 join 的效率高,代碼也簡潔。如果喜歡一個表玩到底,真心推薦 MongoDB
    Foredoomed
        195
    Foredoomed  
       2020-06-04 17:52:59 +08:00
    主键 join 最多 2 张表,多了不推荐
    cs419
        196
    cs419  
       2020-06-04 18:24:20 +08:00
    在一些人眼中 程序员就该 熟悉各种算法、数据结构
    啥? 不会也好意思自称程序员
    大公司屈指可数 而大部分创业公司都是 CRUD BOY 足矣
    你觉着不让用 join 太 low
    你想想你们公司的开发人员算法平均水平溜吗

    没公主命 就别有公主病
    禁用 join 是偷懒 但你想想公司有几个 dba
    或者说你希望担起 dba 的责任 那么领导对你有这个信心?

    其实就算 join 写的垃圾 数据量没大到一定程度也不会很卡
    说白点 要么忍 要么狠 要么滚
    你牛的话 让下属全部写存储过程又怎样
    msg7086
        197
    msg7086  
       2020-06-04 18:34:43 +08:00 via Android   ❤️ 1
    @dawniii 更换技术栈一样有学习成本和招人成本。NoSQL 也不是就没缺点的。对很多公司来说,这种折中的操作更方便。

    像我们写 Rails 的其实只需要操作上层模型就行了,下层 ORM 会自动选用 join 或者单句查询,你改成 NoSQL 的话很多现成的工具都没法用,又要重新做技术储备,重新找类库,甚至重新写组件,我觉得没有太大的优势。
    fancy2020
        198
    fancy2020  
       2020-06-04 18:41:04 +08:00
    不在数据库写 join 那确实需要用到多表 join 的地方怎么办呢,自己把数据查回来然后在代码里 join ?
    akira
        199
    akira  
       2020-06-04 18:45:34 +08:00
    公司规范 是由公司技术负责人提出的,肯定是会统盘考虑公司的业务,技术人员水准等情况,做出的一个最优解。

    这个时候 ,做为一个公司员工,在没有了解完整信息前,要做的,就是遵循公司规范就好。

    唯技术论的形而上学主义要不得。
    blless
        200
    blless  
       2020-06-04 18:55:28 +08:00 via Android
    关系型数据库任何关系都是有代价的,自己看着用呗,反正我们不准用。业务的易变特性决定了代码审计比 SQL 审计手段多且更有效
    1  2  3  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   981 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 20:29 · PVG 04:29 · LAX 12:29 · JFK 15:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.