前段时间,在处理线上慢sql时,遇到过一起因为使用了using Intersect导致性能问题的case,当时会比较疑惑,查了一些才搞明白了。
我们知道Using Intersect并不常见,一般我们在explain的extra字段中更多的看到是:Using index、Using where、Using filesort 、Using tempory等,Using intersect相对少见。
今天我们就来看下,Using Intersect是什么含义吧。
上次遇到的case,我没有记录下来,所以没办法拿它举例了,不过我从stackoverflow看到过一个类似的问题,今天就以这个帖子的例子来说明一下吧。
链接如下:https://stackoverflow.com/questions/4526686/why-would-mysql-use-index-intersection-instead-of-combined-index
使用如下sql进行查询:
SELECT id FROM tbl
WHERE rel = 3 AND type = 3
ORDER BY created;
tbl表中有三个索引,idx_type_rel_created(type, rel, created)、idx_type(type)、idx_rel。
在查看该条sql的执行计划时,发现该sql使用到了Using Intersect(idx_type, idx_rel),而没有使用idx_type_rel_created(type, rel, created)。直觉上,应该用到三个字段的联合索引才对。
mysql> EXPLAIN
-> SELECT id FROM tbl
-> WHERE rel = 3 AND type = 3
-> ORDER BY created\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
type: index_merge
possible_keys: idx_type,idx_rel,idx_rel_type_created
key: idx_type,idx_rel
key_len: 1,2
ref: NULL
rows: 4343
Extra: Using intersect(idx_type,idx_rel); Using where; Using filesort
那么,Using Intersect是在内部是如何做的呢?
Using Intersect是指会在查询时对使用到的索引执行同步扫描分别获取数据集,并对所获得的数据集取交集。
在上述的例子中,则是分别使用idx_type索引、idx_rel索引获取数据集,并对获取数据集的交集。
这样的实现是可能出现性能问题的,比如其中某个索引的效率不高时,或者当内存不足以容量数据集时,都可能会导致这种执行计划执行缓慢。Using Intersect不一定会比联合索引或者单列索引执行效率高。
去解释为什么会选择Using Intersect,而不是联合索引会比较困难,这部分涉及到mysql底层的优化器逻辑。我们今天只讲下当遇到这种情况导致的慢sql时,我们要如何解决问题?
有几种方式:
1.关闭index_merge_intersection。
SET optimizer_switch = 'index_merge_intersection=off'
2.删除不需要的单列索引。在上述的例子中,我们可以看出来,idx_type索引是没有必要加的,因为已经有了联合索引idx_type_rel_created。
3.暂时设置不需要的索引设置为隐藏。
如果我们担心直接删除索引有风险,可以暂时将没有用的索引设置为隐藏。mysql 8.0开始支持隐藏索引(invisible index),也称为不可见索引。隐藏索引不会被优化器使用。
使用ALTER TABLE ... ALTER INDEX语句的VISIBLE或者INVISIBLE选项修改已有索引的可见性:
ALTER TABLE table_name ALTER INDEX idx_name VISIBLE; -- 将索引设置为可见
ALTER TABLE table_name ALTER INDEX idx_name INVISIBLE; -- 将索引设置为隐藏
参考文档:
https://dev.mysql.com/doc/refman/8.0/en/index-merge-optimization.html#index-merge-intersection
https://www.modb.pro/db/29619
https://stackoverflow.com/questions/4526686/why-would-mysql-use-index-intersection-instead-of-combined-index

点个“赞 or 在看” 你最好看!

👇👇👇 谢谢各位老板啦!!!




