暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

MySQL缺少自动消除机制的场景总结

原创 张程 2023-12-23
384

第一章 问题概述

对ORACLE优化器而言,当满足某些场景时(如存在主外键关系、无意义的排序动作等)。即这部分查询动作做与不做,对最终的结果没有影响时,优化器是会省略这部分额外的查询开销的。

但在MySQL环境中,经过总结测试,上述类似场景却没有考虑到自动消除的机制。并且极有可能导致性能问题。

以下总结了部分性能问题场景。涵盖的版本经测试在主流的5.7-8.0均有包含。不排除随着版本的变化可能会有细微的差异表现。但问题的原因及解决方案基本相同。

测试库版本:MySQL8.0.26

测试脚本:

CREATE TABLE test_t1 AS SELECT * FROM information_schema.COLUMNS; ALTER TABLE test_t1 add COLUMN ID INT AUTO_INCREMENT PRIMARY KEY; CREATE TABLE test_t2 AS SELECT * FROM information_schema.COLUMNS; ALTER TABLE test_t2 add COLUMN ID INT AUTO_INCREMENT PRIMARY KEY; CREATE INDEX KEY_TABLE_SCHEMA ON TEST_T2(TABLE_SCHEMA);

第二章 场景一:GROUP BY外连接不必要的表

2.1 案例一:group by不包含聚合列

SQL文本

select test_t1.TABLE_SCHEMA from test_t1 left join test_t2 on test_t1.TABLE_SCHEMA=test_t2.TABLE_SCHEMA where test_t1.ID < 1000 group by test_t1.TABLE_SCHEMA;

查询表现
image.png

执行计划:
image.png

问题分析

SQL中只查询了test_t1表的列。且在关联test_t2后。有一个聚合动作。也是按照test_t1做聚合。因此整段SQL,除了表关联之外,没有访问test_t2表的任何数据。

也就是外连接关联test_t2时,无论关联出多少数据量(0-N行)。均不影响最终的结果。这种情况下对test_t2表的访问完全是可以省略的。
省略后并不影响任何最终结果,但却可以减少大量的数据访问。

优化建议

去掉不必要的表关联。

select test_t1.TABLE_SCHEMA from test_t1 where test_t1.ID < 1000 group by test_t1.TABLE_SCHEMA;

调整后的执行效率:
image.png

2.2 案例二:包含聚合列但与关联表无关

SQL文本

select test_t1.TABLE_SCHEMA,max(test_t1.id) from test_t1 left join test_t2 on test_t1.TABLE_SCHEMA=test_t2.TABLE_SCHEMA where test_t1.ID < 1000 group by test_t1.TABLE_SCHEMA;

查询表现

image.png

执行计划:

image.png

问题分析

SQL中只查询了test_t1表的列。且在关联test_t2后。有一个聚合动作。也是按照test_t1做聚合。因此整段SQL,除了表关联之外,没有访问test_t2表的任何数据。

也就是外连接关联test_t2时,无论关联出多少数据量(0-N行)。均不影响最终的结果。这种情况下对test_t2表的访问完全是可以省略的。

省略后并不影响任何最终结果,但却可以减少大量的数据访问。

优化建议

去掉不必要的表关联。

select test_t1.TABLE_SCHEMA,max(test_t1.id) from test_t1 where test_t1.ID < 1000 group by test_t1.TABLE_SCHEMA;

调整后的执行效率:

image.png

第三章 场景二:关联唯一性列

3.1 案例一:外键表关联主键表

给T1表添加外键引用T2表主键:

alter table test_t1 add constraint FK_t1_ID foreign key(ID) REFERENCES test_t2(ID);

主键表的主键列具有唯一约束。且外键列一定在主键表中存在。

SQL文本

select test_t1.TABLE_SCHEMA from test_t1 inner join test_t2 on test_t1.id=test_t2.id where test_t1.TABLE_SCHEMA < 'x';

查询表现

image.png

问题分析
SQL中只查询了test_t1表的列。尽管使用内连接关联test_t2。但存在主外键关联(主键表test_t1的外键列id一定在主键表test_t2中的主键列中存在)。

也就是关联test_t2时,只会关联出唯一的一行主键列数据。均不影响最终的结果。这种情况下对test_t2表的访问完全是可以省略的。

省略后并不影响任何最终结果,但却可以减少大量的数据访问。

优化建议

外键表关联主键表时,且没有访问主键表的列,省略关联主键表动作。

select test_t1.TABLE_SCHEMA from test_t1 where test_t1.TABLE_SCHEMA < 'x';

调整后的执行效率:
image.png

3.2 案例二:外连接关联唯一性列

SQL文本

select test_t1.TABLE_SCHEMA from test_t1 left join test_t2 on test_t1.id=test_t2.id where test_t1.TABLE_SCHEMA < 'x';

查询表现

image.png

问题分析

SQL中只查询了test_t1表的列。且通过外连接关联test_t2表,而关联列上是主键列,不会关联出重复的多行数据。

因此,在查询条件不包含test_t2表时,关联test_t2表的动作可以省略。
省略后并不影响任何最终结果,但却可以减少大量的数据访问。

优化建议和问题总结

外连接关联唯一约束的表,且没有访问主键表的列,省略关联动作。

select test_t1.TABLE_SCHEMA from test_t1 where test_t1.TABLE_SCHEMA < 'x';

调整后的执行效率:
image.png

第四章 场景三:聚合查询包含了不必要的排序

4.1 案例一:单表场景:

SQL文本

select count(*) from test_t2 where TABLE_SCHEMA < 'x' order by COLUMN_NAME;

查询表现

image.png

执行计划:
image.png

问题分析

SQL中只查询了count聚合列。但却在最后包含了排序动作。出现了额外的回表代价。从Extra部分的Using index condition也能确认。

这部分排序完全可以省略。

优化建议

去掉不必要排序。

select count(*) from test_t2 where TABLE_SCHEMA < 'x';

调整后的执行效率:
image.png

4.2 案例二:多表场景:

SQL文本

select count(*) from test_t1 left join test_t2 on test_t1.TABLE_SCHEMA=test_t2.TABLE_SCHEMA where test_t1.ID < 1000 order by test_t2.COLUMN_NAME;

查询表现
image.png

执行计划:
image.png

问题分析

SQL中只查询了count聚合列。但却在最后包含了排序动作。出现了额外的对test_t2的回表代价。
这部分排序完全可以省略。

优化建议

去掉不必要排序。

select count(*) from test_t1 left join test_t2 on test_t1.TABLE_SCHEMA=test_t2.TABLE_SCHEMA where test_t1.ID < 1000;

调整后的执行效率:

image.png

image.png
调整后,尽管仍然访问了test_t2表,但是从Extra部分看为Using index,只访问索引即可完成查询。

第五章 问题总结

通过上述三个场景的分析。

场景一、二:
关联test_t2表完全不必要,但是SQL文本中包含,优化器也没有自动的消除这种不必要的关联查询。在关联条件过滤性不好的时候,造成性能问题。

场景三:
只是查询聚合列,排序动作并不影响聚合结果的返回,但是多一步排序且可能大量的数据回表问题。最终出现了性能问题。

因此SQL书写的时候,就要求只做必要的查询。省略任何不必要的动作。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论