一、联合索引
联合索引指对表上多个列进行索引,如以下创建表t4:
CREATE TABLE t4(
a INT,
b INT,
PRIMARY KEY(a),
KEY idx_a_b(a,b)
) ENGINE=INNODB;
Idx_a_b就是联合索引,联合索引也是B+树,不同的时,它的键值是多个值,如下图所示:
可以看出,键值都是排序的,对于a=1时,b的值有1,2是从小到大排序。通过叶子节点可以读出所有数据。
因此,对于SELECT * FROM t4 WHERE a=xx AND b=xx;是可以使用到(a,b)这个索引的。对于单列查询SELECT * FROM t4 WHERE a=xx 也可利用到这个索引。
因为索引对于第2个键值进行了排序,所以SELECT * FROM t4 WHERE a=xx ORDER BY b;也使用到了索引。
同时,如果索引列为(a,b,c),SELECT * FROM t WHERE a=x AND b=x ORDER BY c,也能用到三个列的索引。
二、覆盖索引
覆盖索引(covering index),即从辅助索引即可获取得查询的数据,而不需要查询聚集索引中的记录。好处是辅助索引不包含整行记录的信息,所以大小远小于聚集索引,减少了大量的IO操作。
对于辅助索引来讲,它包含了主键的信息,因此它叶子节点上存放的数据为(primary key1,primary key2,…key1,key2…),下面的语句可以使用辅助索引来完成查询:
SELECT key2 FROM table WHERE key1=xxx;
SELECT primary key2,key2 FROM table WHERE key1=xxx;
SELECT primary key1,key2 FROM table WHERE key1=xxx;
SELECT primary key1,primary key2,key1,key2 FROM table WHERE key1=xxx;
覆盖索引另一个好处是对统计来说的,一般来说如果表有辅助索引,就会选择辅助索引来统计,而不是通过聚集索引。
SELECT COUNT(*) FROM t4 WHERE b>xx AND b<xx;
正常情况下是不会选择(a,b)索引的,但由于是count操作,优化器会选择辅助索引。
三、不使用索引的情况
假设在订单表查询以下信息:
Select * fro orderdetails where orderid>1000 and orderid <10200;
当前表有的索引有orderid索引,主键索引,以上SQL理论上可以使用orderId索引,但因为查询的是整行信息,用不上覆盖索引,如果用orderid索引,在查询后还要通过bookmark查询聚集索引,而进行书签查找是无序的,是离散读,虽然orderid索引是有序的。如果查询的数据量少,优化器还是会选择辅助索引,如果查询的数据量大(一般占20%时),优化器就会选择聚集索引,即全表扫描的方式。
四、索引提示
使用索引提示的情况:
• 优化器选择了错误的索引,导致SQL运行很慢。一般来说比较少见;
• SQL语句可选择的索引很多,优化器选择索引的开销比SQL语句本身开销大。
语句为:
SELECT * FROM t4 USE INDEX(a) WHERE a=xx ;
这个情况也是建议使用索引a,如果强制使用索引a需要通过以下SQL:
SELECT * FROM t4 FORCE INDEX(a) WHERE a=xx ;
五、Multi-Range Read(MRR)优化
六、Index Condition Pushdown(ICP)优化
参考《MySQL技术内幕 -InnoDB存储引擎》整理,如侵权请联系vinin@163.com。