不知道大家有没有遇到过一个 sql 连了 7,8 张表

2017-03-04 13:32:59 +08:00
 chaleaoch
在实际的生产环境中,这样会带来很大的效率问题吗?
昨天面试一个大兄弟,单张表只有 7--8 万的记录.连 7,8 张表查询,需要 7--8 秒.我表示很差异.

当然了目前我所遇到过的最大连表只连三张,单表数据也不是很大.大概是一张几千,另一张几百万的样子.

不过很快就查出来了.
4276 次点击
所在节点    数据库
86 条回复
ebony0319
2017-03-04 21:44:56 +08:00
cchilar
2017-03-04 22:03:28 +08:00
BI 里经常会遇到。如果没走索引,有时候说不定能跑半小时。
shijingshijing
2017-03-04 22:15:21 +08:00
@chaleaoch 其实我比较关心的是,来一个真正的案例,然后用纯 join 实现,纯子查询实现,部分 join+部分子查询实现,各个方案都在尽量优化的情况下来 PK 一把。以前在做的时候,也是事先在网上做了调研的,貌似 Stackoverflow 上面有比较。不过我最终还是放弃了 join 而选择了子查询,这不是经过仔细的考量得出结论后选择的,我当时的直觉是如果是三四个表 join ,在 key 和索引的帮助下,效率应该也还可以,但是一旦表多了之后,我个人感觉数据库性能会有急剧的下降。当然这都是我自己的感觉。当时时间紧迫,业务急着上线,凭直觉做出了选择,后来业务也能扛得住就没有再去关心过这个问题。

现在我确实也非常想听听碰到过这个问题的其他同行的经历以及对应的处理方法。
CRVV
2017-03-04 22:15:55 +08:00
这事丝毫不奇怪

而且,查询要花多少时间和 JOIN 了几张表,每张表里有几行,关系并不大。主要看 SQL 是怎么写的,有没有加正确的索引

SELECT * FROM t1 CROSS JOIN t2 CROSS JOIN t3 WHERE t1.a || t2.b || t3.c LIKE '%abcd%' 当然很慢

SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id1 ... INNER JOIN t100 ON t1.id = t100.id1 WHERE t1.id < 10 AND t1.id > 0
如果 t1 的 id 和其它表的 id1 都有 UNIQUE INDEX ,这个一定很快
hj2002007
2017-03-04 22:21:07 +08:00
现在 mysql5.7 优化了大量查询 其实 join 不是很耗时 关键还是 索引+合理利用 rendis 等缓存 mysql 的子查询效率不好 还是慎用
阿里自己的 mysql 已经改成 不是 mysql 了吧
join 尽量不要超十张表,太多的话 就做汇总表吧
一般 一些不需要进行排序的字段 就不要 select 了 只 select 必要的字段 用于缓存的查询 这样在 一定数据量下 响应的速度也是很快的
我还是喜欢 先用数据库解决问题 毕竟很多问题 都是关系问题。 确实解决不了 再用程序解决。
mingyun
2017-03-04 22:43:15 +08:00
恐怖,工作几年没用过
ikaros
2017-03-04 22:56:48 +08:00
连表多肯定不是问题,问题应该是连的字段没索引
wuhanchu
2017-03-04 23:50:32 +08:00
还真的是见过。。
renyiqiu
2017-03-04 23:55:18 +08:00
@hector 这不得累死那些后面接手的人,因为不是每个人的数据库基础都那么好,我其实比较讨厌偏向数据库来处理负责业务的公司
dong3580
2017-03-04 23:59:40 +08:00
连了几个表是小事,我以前维护过的项目,甚至 MSSQL 和 MYSQL 连起来了,维护的头大,
hj2002007
2017-03-05 00:00:05 +08:00
@renyiqiu 如果对方写的好 还是可以学习的 多学点总是好的
hj2002007
2017-03-05 00:00:44 +08:00
@dong3580 怎么连的 很好奇啊
dong3580
2017-03-05 00:06:17 +08:00
@hj2002007
.NET 里面的 ado.net ,后来我给他改成了映射实体,然而效果不理想,我接手的时候打开一个关联列表页面,大约 50 条数据的联动信息(这个信息非常的多)大约 20s 。后来又回归到.NET 自带的连接查询封装起来,加了大量的缓存优化和任务,大约降到了 5S ,然后效果还是不好。

总结下来,如果要是大量做到快,需要自己用基础的类来封装优化,用现成的 在量大且并发多的情况下完全不行。

当然,这里已经不涉及到表优化之类的,加主键和视图已经不能满足了。
wind3110991
2017-03-05 00:15:52 +08:00
join 多少张表,其实并没有太大关系的,
主要开发人员是别 XJB 乱用外键,最好别用,不然分分钟炸给你看
hj2002007
2017-03-05 00:20:10 +08:00
@dong3580 嗯嗯 受教受教 我都是用 php 都是自己写 sql 语句 没有 orm 之类 都是先把需求写成 sql 然后优化到可以接受的范围 再开始写程序。
hj2002007
2017-03-05 00:24:49 +08:00
@wind3110991 用程序来维护外键 不是挺好的嘛 不过 Hibernate 之类的 外键判断真是分分秒秒崩 啊
wind3110991
2017-03-05 00:52:27 +08:00
@hj2002007 带外键的关系数据库做集群或者容灾时,双主、主从同步都有无法预料的问题,坑太多,
有时同步失败,只能重新做表
konakona
2017-03-05 00:59:00 +08:00
不是不行,只是效率奇低。
1. 优化每张表的索引和碎片
2. 尽量使用子查询,或先取出表 1 里相关的数据(通过 selec * from where ,或者使用 1 个子查询,比 LEFTJOIN 效率高一丢丢。数据量越多, LEFTJOIN 效率越低。)

这么说:

哪怕你将这 7-8 个表的数据,不写 where 。全部拿出来放到对应的 7-8 个变量里。通过程序语言(如 python 、 PHP )用逻辑语句( IF 和 foreach )去遍历,找到数据。效率都高出题主里的那种不知道多少倍。
wind3110991
2017-03-05 01:01:58 +08:00
@konakona 工程中最好不要使用 select *
https://www.zhihu.com/question/37777220
eyp82
2017-03-05 02:57:37 +08:00
@chaleaoch 要么看看能不能一条 SQL 拆开成多条执行(这个好像有些 MySQL DBA 推荐), 要么重新设计一下 schema, 适当增加冗余减少 join (看你的 DML 和查询的比例), 需要权衡.

ERP 说实话也没太好的方案, 即使是 SAP 的 ERP, 那 SQL 抓出来也是让人头疼, 动不动几百行的 SQL 语句, 跑起来蜗牛一样, 先天不足再优化也不没大用. 估计大家都习惯了,反正并发也不会太高, 主要复杂在业务逻辑.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/344855

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX