——纪念一次mysql子查询打满CPU...
sql原文大致如下:
select * from A where id in (select B.a from B where B.b in (select C.a from C where C.b = ?))
涉及到的查询字段都有索引,但是由于mysql对子查询的优化做的不好,查询引擎对于子查询很容易选错合适的索引,导致在线上实际跑的时候,外侧的大表A没有走到id字段的主键索引,导致访问类型type=ALL遍历全表,检索了2KW行数据,把cpu拉满了。。
生产实际执行sql的explain详情:
总结:改掉随手写子查询的陋习。。mysql尽量避免子查询,改用join方式(或者exist,不过感觉exist不好阅读)可以避免此类问题。
查这个问题时看到的相关文章:
1.遇到同样问题的老哥:https://blog.csdn.net/kevinxxw/article/details/88718663
2.mysql explain详解:https://www.cnblogs.com/tufujie/p/9413852.html
3.mysql 内外连接相关:https://blog.csdn.net/qq_40086556/article/details/81807849
4.深入理解MySql子查询IN的执行和优化:https://blog.csdn.net/lppl010_/article/details/79890050
5.mysql表连接相当于做了笛卡尔积,使用 join xxx on xxx 方式可以优化,结果是局部笛卡尔积 (ON语句的执行是在JOIN语句之前的,也就是说两张表数据行之间进行匹配的时候,会先判断数据行是否符合ON语句后面的条件,再决定是否JOIN)
6.mysql 内连接/左连接会出现笛卡尔积? https://blog.csdn.net/zy_281870667/article/details/81046573
sql执行顺序:
——纪念一次mysql慢查询...
大表做分页查询时,应该把 limit a,b 改成 where id > n limit b. 原因:当a的值很大时,会扫描很多行导致sql很慢;记录上一次查询到数据的id,然后用where id > n,能减少扫描的行数。
ALTER TABLE vord_worksheet MODIFY ext varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci not NULL default '' COMMENT 'ext';