Cardinality


Cardinality数值示意了该索引字段的反复率水平,数值越大代表反复率越低,PRIMIARY是自增的,可能保障插入/更新数据依照磁盘程序进行,然而id字段因为没有什么可筛选的含意,不能进行筛选查问。

咱们为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个字段。

咱们建设的索引是3个字段联结的,然而查问的时候只用两个字段进行筛选,也会应用这个索引的前两个字段进行筛选。

还是应用两个字段进行筛选,只是用了c而不是b,查问应用了index这个索引然而key_len是202,阐明只用了a的索引局部。这景象是“最左匹配准则”带来的。也就是说要像最大化利用索引,筛选的时候要依据建设索引的字段程序就行查问,如果where等筛选/分组/排序操作能命中索引的局部程序字段,则也会应用这部分程序字段进行索引。

SELECT中有索引的字段,优化器会抉择应用索引查问,所以查问进去的后果是以page_name排序的。
反之,如果SELECT中没有索引字段,或者只有局部蕴含,或者是查问 * ,都不会应用索引进行查问

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

SELECT a, e FROM test WHERE a = '2';

(这个工夫应该是利用了缓存的根底上的工夫,第一次进行全表查问的工夫是7秒多,同样的sql再次查问就变成了1+秒,试过将query_cache_type和query_cache_size都设置为0,还是这样,有说法是操作系统级别的缓存是无奈限度的。如果一开始就建设索引,并SELECT a FROM test,也是六七秒,所以狐疑查问后都会有缓存,那么以下的工夫都是在这个根底上进行截图)

建设一个联结索引

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

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

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

发现了只利用索引的一个字段进行查问,查问破费的工夫比全表查问还要慢很多,然而索引字段利用率大,查问破费的工夫就很少了。

删除下面建设的索引,再建设一个不蕴含a的索引

ALTER TABLE testDROP INDEX index,ADD INDEX index(b, c);

SQL1的执行如下:

相当于查问type是all,耗时比之前的蕴含a索引的快


同样的SQL2,能够看到索引利用长度是1,然而速度是简直一样的,这里能够看进去a的反复率太高,是索引这个字段的意义并不大,而且会减少索引key的长度,带来B+Tree每一个节点的键值存储量缩小,树的构造可能会更深,进而查问更慢。

总结:

  • 联结索引中每一个索引代表的权重是不一样的,比方索引(a, b, c),a是百,b是十,c是个位,那么假如筛选条件是b和c,依据B+Tree构造,索引失去的最终是扩散的,所以应用索引的意义就不大,天然就不会应用索引了
  • 建设的索引字段须要充分利用,不失当的应用可能会比全表查问来的更慢
  • 为Cardinality很小的字段建设索引的必要性有待商讨,个别状况下反复率很大的字段不须要建设索引。

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