MySQL索引的探索

Cardinality

image.png
Cardinality数值表示了该索引字段的重复率程度,数值越大表明重复率越低,PRIMIARY是自增的,可以保证插入/更新数据按照磁盘顺序进行,可是id字段由于没有什么可筛选的含义,不能进行筛选查询。sql

咱们为data_unique_key创建了一个惟一索引,这个属性的值是一些筛选字段的md5值,若是是具体查询某一条数据的话,能够md5后查询data_unique_key为该值,速度很快。缓存

对于重复率很是大的字段,探索一下为a创建索引是否有必要。
a的Cardinality是21
b的Cardinality是77
c的Cardinality是1305优化

最左匹配原则

ALTER TABLE test ADD INDEX index (a, b, c);

假设如今有一张test表,咱们先创建一个联合索引,索引包含a,b,c3个字段。
image.png
咱们创建的索引是3个字段联合的,可是查询的时候只用两个字段进行筛选,也会使用这个索引的前两个字段进行筛选。
image.png
仍是使用两个字段进行筛选,只是用了c而不是b,查询使用了index这个索引可是key_len是202,说明只用了a的索引部分。这现象是“最左匹配原则”带来的。也就是说要像最大化利用索引,筛选的时候要根据创建索引的字段顺序就行查询,若是where等筛选/分组/排序操做能命中索引的部分顺序字段,则也会使用这部分顺序字段进行索引。
image.png
SELECT中有索引的字段,优化器会选择使用索引查询,因此查询出来的结果是以page_name排序的。
反之,若是SELECT中没有索引字段,或者只有部分包含,或者是查询 * ,都不会使用索引进行查询spa

a是否有必要成为索引字段

SELECT a, e FROM test WHERE a = '2';
image.png
(这个时间应该是利用了缓存的基础上的时间,第一次进行全表查询的时间是7秒多,一样的sql再次查询就变成了1+秒,试过将query_cache_type和query_cache_size都设置为0,仍是这样,有说法是操做系统级别的缓存是没法限制的。若是一开始就创建索引,并SELECT a FROM test,也是六七秒,因此怀疑查询后都会有缓存,那么如下的时间都是在这个基础上进行截图)操作系统

创建一个联合索引3d

ALTER TABLE test ADD INDEX index(`a, b, c`);
-- SQL1:
SELECT a, e  FROM test WHERE a = '1' ;

image.png

-- SQL2:
SELECT a, e FROM test WHERE a = '1' AND b = 2;

image.png

-- SQL3:
SELECT a, e FROM test WHERE a = '1' AND data_type = 2 AND c = 'math';

发现了只利用索引的一个字段进行查询,查询花费的时间比全表查询还要慢不少,可是索引字段利用率大,查询花费的时间就不多了。code

删除上面创建的索引,再创建一个不包含a的索引blog

ALTER TABLE test
DROP INDEX index,
ADD INDEX index(b, c);

SQL1的执行以下:
image.png
至关于查询type是all,耗时比以前的包含a索引的快
image.png
image.png
一样的SQL2,能够看到索引利用长度是1,可是速度是几乎同样的,这里能够看出来a的重复率过高,是索引这个字段的意义并不大,并且会增长索引key的长度,带来B+Tree每个节点的键值存储量减小,树的结构可能会更深,进而查询更慢。排序

总结:索引

  • 联合索引中每个索引表明的权重是不同的,好比索引(a, b, c),a是百,b是十,c是个位,那么假设筛选条件是b和c,根据B+Tree结构,索引获得的最终是分散的,因此使用索引的意义就不大,天然就不会使用索引了
  • 创建的索引字段须要充分利用,不恰当的使用可能会比全表查询来的更慢
  • 为Cardinality很小的字段创建索引的必要性有待商榷,通常状况下重复率很大的字段不须要创建索引。

(以上截图都模糊掉自身数据,用a,b,c来代替)

相关文章
相关标签/搜索