

主机类型:阿里云 操作系统:CentOS release 7.4 存储:Alibaba Cloud ECS 内存:64 G CPU型号:Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz ( 1 U * 8 core) CPU核数:16CORE 数据库环境:MySQL5.7.27 存储引擎:InnoDB

通过分析慢日志定位慢SQL,分析慢SQL原因; 追溯SQL执行历史数据,分析关键指标在SQL多次执行的波动,这些关键指标可以用来做为SQL健康度参考指标。 用实际数据来验证推断,排除掉其它干扰因素,定位SQL慢的根本原因,帮助快速修复。

SELECT *
FROM tab_a
WHERE ID IN (SELECT c_id FROM tab_b);
复制
SELECT *
FROM tab_a
WHERE ID IN (SELECT c_id FROM tab_b);
复制

就这个SQL的执行计划本身来说还是不错的(MySQL查询转换做的不错),我想说的主要关注点在FirstMatch(tab_a)上。
等价传播可以跨越semi-join边界,但是不能跨越子查询边界。因此,使用FirstMatch将子查询转换成semi-join可以提供一个更好的执行计划; 只有一种方式使用in->exists策略,mysql会无条件地使用。对于FirstMatch策略,优化器可以选择是否应该在子查询中使用的所有表都位于join前缀时运行FirstMatch策略,或者在稍后的某个时间点运行FirstMatch策略;
FirstMatch策略意味着子查询的表必须在父查询中的表之后被引用,FirstMatch支持相关子查询;不能应用于子查询带有group by或聚合函数的场景。
SELECT a.*
FROM tab_a a
WHERE exists (SELECT c_id FROM tab_b b where a.id=b.c_id);
复制

如果连接列(cr_id)上建立了索引,那么查询 tab 时可以通过索引查询,而不是全表查询; 使用 exists,一旦查到一行数据满足条件就会终止查询,不用像使用 IN 时一样进行扫描全表(NOT EXISTS 也一样)
减少临时表也是在 SQL优化中需要注意的点,子查询的结果会被看成一张新表(临时表),这张新表与原始表一样,可以通过 SQL 进行操作。但是频繁使用临时表会带来两个问题:
临时表相当于原表数据的一份备份,会耗费内存资源;
很多时候(特别是聚合时),临时表没有继承原表的索引结构。
4、其他代替IN的方案
SELECT distinct a.*
FROM tab_b b left join tab_a a on b.c_id=a.id
复制

为了排除重复数据, DISTINCT 也会进行排序,而排序操作一般是要避免的,怎么避免?
5、使用 EXISTS 代替 DISTINCT

总结
参数是子查询时,使用 EXISTS 或者 JOIN 代替 IN;
在 SQL 中,很多运算都会暗中进行排序,尽量规避这些运算;
SQL 的书写,尽量往索引上靠,避免用不上索引的情况;
尽量减少使用临时表。
文章转载自数据与人,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
墨天轮个人数说知识点合集
JiekeXu
432次阅读
2025-04-01 15:56:03
MySQL数据库当前和历史事务分析
听见风的声音
423次阅读
2025-04-01 08:47:17
MySQL 生产实践-Update 二级索引导致的性能问题排查
chengang
381次阅读
2025-03-28 16:28:31
MySQL 9.3 正式 GA,我却大失所望,新特性亮点与隐忧并存?
JiekeXu
347次阅读
2025-04-15 23:49:58
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
346次阅读
2025-04-17 17:02:24
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
326次阅读
2025-04-15 14:48:05
云和恩墨杨明翰:安全生产系列之MySQL高危操作
墨天轮编辑部
305次阅读
2025-03-27 16:45:26
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
292次阅读
2025-04-07 12:14:29
云和恩墨钟浪峰:安全生产系列之SQL优化安全操作
墨天轮编辑部
239次阅读
2025-03-31 11:08:20
记录MySQL数据库的一些奇怪的迁移需求!
陈举超
192次阅读
2025-04-15 15:27:53