MySQL索引优化总结(二)
在优化数据库索引中,了解到在新版本的MySQL中,有两个比较重要的新技术,Push down 和 Index merge。于是查了资料做了一些总结。
Push down
索引下推(Index Condition Pushdown)用于优化MySQL通过索引检索表的过程。
如果没有ICP,存储引擎会遍历索引去定位表中的行,并返回给MySQL服务器。开启ICP后,如果在查询的WHERE条件中有部分条件可以使用索引,那么MySQL服务器会下推这部分索引到存储引擎,然后通过索引过滤的WHERE条件在存储引擎层进行数据过滤,而非将所有通过索引access到的结果传递到MySQL服务器层进行WHERE过滤。
当使用Push down时:
获取下一行的索引元组(但不是完整的行)。
尝试只使用索引列检查是否符合条件。如果条件不满足,回到步骤1。只有满足条件才会回表读取数据。
如果满足下推的索引条件,存储引擎通过索引元组定位和读取整行数据并返回给MySQL服务层。
MySQL服务层评估没有被下推到存储引擎的WHERE条件,如果该行数据满足WHERE条件则使用,然后回到步骤1。

如果没有使用该技术的情况下,会在读取索引元组之后直接在表中定位读取整行数据。
在一个测试表中建立一个索引:
ALTER TABLE `cms_article`
ADD INDEX `TEST_INDEX` (`audit_status` ASC, `create_by` ASC, `update_by` ASC);
开启Push down后:
mysql> set optimizer_switch = "index_condition_pushdown=on";
mysql> explain select * from cms_article where audit_status = 0 and update_by = '1'\G;
******** 1. row ********
id: 1
select_type: SIMPLE
table: cms_article
type: ref
possible_keys: TEST_INDEX
key: TEST_INDEX
key_len: 5
ref: const
rows: 735
Extra: Using index condition
对比开启前:
mysql> set optimizer_switch = "index_condition_pushdown=off";
mysql> explain select * from cms_article where audit_status = 0 and update_by = '1'\G;
******** 1. row ********
id: 1
select_type: SIMPLE
table: cms_article
type: ref
possible_keys: TEST_INDEX
key: TEST_INDEX
key_len: 5
ref: const
rows: 735
Extra: Using where
可以看出即使搜索条件不符合联合索引的最左匹配原则,但是MySQL还是对搜索进行了优化。
Index merge
在多个列上建立独立的单列索引在之前并不会提高查询速度,因为每次查询只会使用到一个索引。但是在索引合并(Index merge)技术下,可以做到最大限度利用多个索引定位行。
索引合并有三种情况:OR条件的Union,AND条件的Intersection,OR和AND条件的组合Union&Intersection。Index merge其实就是分别通过对两个独立的索引进行过滤之后,将过滤之后的结果聚合在一起,然后在返回结果集。
mysql> explain select * from cms_article where proprietary_id = '345345' or del_flag = 0 and audit_status = 0 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: cms_article
type: index_merge
possible_keys: INDEX_PRO,INDEX_DEL_AUDIT
key: INDEX_PRO,INDEX_DEL_AUDIT
key_len: 259,10
ref: NULL
rows: 734
Extra: Using union(INDEX_PRO,INDEX_DEL_AUDIT); Using where
其type表明使用了索引合并,且在Extra中详细说明了合并方式。这里的OR条件就是利用了一个union方式的索引合并,将 INDEX_PRO 和 INDEX_DEL_AUDIT 合并后共同计算返回结果。
虽然是一个优化技术,但索引合并更多时候说明了表上的索引创建有问题,在《高性能MySQL》中给出了理由:
当对多个索引进行相交操作时,通常需要一个包含所有相关项的多列索引,而不是多个独立的单个索引。
当对多个索引进行联合操作时,需要耗费大量资源进行索引合并,特别是索引选择性不高的情况下,需要扫描并返回大量的数据进行计算。
在并发大的情况下谨慎使用Index merge。