覆盖索引,什么情况下优化器会选择使用覆盖索引
覆盖索引,什么情况下优化器会选择使用覆盖索引
InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询的记录(此时不能够使用select * 操作,只能对特定的索引字段进行select),而不需要查询聚集索引中的记录。使用覆盖
索引的一个好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。对于InnoDB存储引擎的辅助索引而言,由于其包含了主键信息,因此其叶子节点存放的数据为(primarykey1,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,key2 FROM table WHERE key1=xxx;
CREATETABLEbuy_log(
userid INT UNSIGNED NOT NULL,
buy_date DATE
)ENGINE=InnoDB;
ALTER TABLE buy_log ADD KEY (userid);
ALTER TABLE buy_log ADD KEY (userid,buy_date);
覆盖索引的另一个好处是对某些统计问题而言的。还是对于上题创建的表buy_log,要进行举例说明。
SELECT COUNT(*) FROM buy_log;InnoDB存储引擎并不会选择通过查询聚集索引来进行统计。由于buy_log表上还有辅助索引,而辅助索引远小于聚集索引,选择辅助索引可以减少IO操作。
在通常情况下,诸如(a,b)的联合索引,一般是不可以选择列b中所谓的查询条件。但是如果是统计操作,并且是覆盖索引的,则优化器会进行选择,如下述语句:SELECT COUNT(*)FROM buy_log WHERE buy_date>=‘2011-01-01’ANDbuy_date<’2011-02-01’
表buy_log有(userid,buy_date)的联合索引,这里只根据列b进行条件查询,一般情况下是不能进行该联合索引的,但是这句SQL查询是统计操作,并且可以利用到覆盖索引的信息,因此优化器会选择该联合索引.
联合索引
联合索引是指对表上的多个列进行索引。
CREATE TABLE buy_log(
userid INT UNSIGNED NOT NULL,
buy_date DATE
)ENGINE=InnoDB;
ALTER TABLE buy_log ADD KEY (userid);
ALTER TABLE buy_log ADD KEY (userid,buy_date);
以上代码建立了两个索引来进行比较。两个索引都包含了userid字段。
情况1: 如果只对于userid进行查询,如:SELECT * FROM buy_log WHERE userid=2;索引选择:优化器最终的选择是索引userid,因为该索引的叶子节点包含单个键值,所以理论上一个页能存放的记录应该更多。
情况2:SELECT * FROM buy_log WHERE userid=1 ORDER BY buy_date DESC LIMIT 3;索引选择:优化器使用了(userid,buy_date)的联合索引userid_2,因为在这个联合索引中buy_date已经排序好了。根据该联合索引取出数据,无须再对buy_date做一次额外的排序操作。
情况 3:假如三个字段的联合索引。如:对于联合索引(a,b,c)来说,下列语句同样可以直接通过联合索引得到结果,不需要filesort的排序操作:
SELECT…FROM TABLE WHERE a=xxx ORDER BY b
SELECT…FROM TABLE WHERE a=xxx AND b=xxx ORDER BY c
1
2
但是对于下面的语句,联合索引不能直接得到结果,其还需要执行一次filesort排序操作,因为索引(a,c)并未排序:
SELECT…FROM TABLE WHERE a=xxx ORDER BY c
1
- 点赞
- 收藏
- 关注作者
评论(0)