高性能的索引策略【高性能mysql第三版笔记】

1. where右边使用独立的列

2. 前缀索引和索引选择性

前缀索引:索引最开始的部分字符,可以大大节约索引空间,从而提供索引效率;
索引选择性:不重复的索引值和数据表记录的总数的比值,范围在0-1之间,比值越大,表示索引的选择性越高,则查询效率越高。

3 对于blob,text或很长的varchar类型的列,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度。

demo分析如下:


高性能的索引策略【高性能mysql第三版笔记】_第1张图片
image.png

高性能的索引策略【高性能mysql第三版笔记】_第2张图片
image.png

于是,我们此时可以确定合适的前缀索引:

ALTER TABLE sakila.city_demo ADD KEY (city(7));

4.多列索引

在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能。

  • 当服务器对多个索引做相交操作时(通常是多个AND条件),通常意味着需要一个包含所有相关列的多列索引,而不是多个独立的单列索引;
  • 当服务器对多个索引做联合操作时(通常有多个OR条件),通常需要耗费大量CPU和内存资源在算法的缓存、排序和合并操作上,特别是其中有些索引的选择性不高,需要合并扫描返回的大量数据的时候;
  • 更重要的是,优化器不会把这些计算到“查询成本”中,优化器只关心随机页面读取。这会使得查询的成本被低估,导致执行计划还不如直接走全表扫描。这样做不但会消耗更多的CPU和内存资源,还可能影响查询的并发性,还不如在MySQL更早的版本一样,将查询改写成union的方式往往更好。、

5 选择合适的索引列顺序

索引的顺序依赖于使用该索引的查询,并且同时需要考虑如何更好地满足排序和分组的需要(下面内容适用B-tree索引)。

在一个多列的B-tree索引中,索引列的顺序意味着索引首先按照最左列进行排序,其次是第二列,所以,索引可以按照升序或者降序进行扫描,以满足精确符号列顺序的ORDER BY、GROUP BY和DISTINCT等子句的查询需求。

如何选择列顺序有一个经验法则:将选择性最高的列放到索引的最前列。然而这通常不如避免随机IO和排序那么重要,考虑这个问题需要更全面。

当不需要考虑排序和分组时,将选择性最高的列放在前面通常是最好的。这时候索引的作用只是用于优化Where条件的查找。然而,性能不只是依赖所有索引列的选择性(整体基数),也和查询条件的具体值有关,也就是和值的分布有关。这和前面说的选择前缀的长度需要考虑的地方一样,可能需要根据哪些运行频率最高的查询来调整索引列的顺序,让这种情况下索引的选择性最高。
demo如下:


高性能的索引策略【高性能mysql第三版笔记】_第3张图片
image.png

高性能的索引策略【高性能mysql第三版笔记】_第4张图片
image.png

6 聚簇索引

聚簇索引不是一种单独的索引类型,而是一种数据存储方式。InnoDB聚簇索引实际上在同一个结构中保存了B-tree索引和数据行。当表有聚簇索引时,它的索引行实际上存放在索引的叶子页中。术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起。因为无法同时把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。

7 覆盖索引

通常大家都会根据查询的where条件来创建合适的索引,不过这只是索引优化的一个方面。设计优秀的索引应该考虑到整个查询,而不单单是where条件部分。索引确实是一种查找数据的高效方式,但是MySQL也可以使用索引来直接获取列的数据,这样就不需要读取数据行。如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要回表查询呢?如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。

不是所有的类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引列的值,而哈希索引、空间索引和全文索引等都不存储索引列的值。所以MySQL只能使用Be-tree所以做覆盖索引。
demo1:


高性能的索引策略【高性能mysql第三版笔记】_第5张图片
image.png

demo2:


高性能的索引策略【高性能mysql第三版笔记】_第6张图片
image.png

有办法解决以上的两个问题,需要重写查询并巧妙地设计索引。先将索引扩展至覆盖三个数据列(artist,title,prod_id),然后按如下方式重写查询:


高性能的索引策略【高性能mysql第三版笔记】_第7张图片
image.png

8 使用索引扫描来做排序

MySQL有两种方式可以生成有序的结果:1.排序操作;2.按索引顺序扫描。
如果Explain出来的type列的值是“index”,则说明使用了索引扫描来做排序。

扫描索引本身是很快的,因为只需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那就不得不扫描每一条索引记录就都回表查询一次对应的行。这基本上都是随机I/O,因此按索引顺序读取数据的速度通常要比顺序地全表扫描慢,尤其是在I/O密集型的工作负载时。

MySQL可以使用同一个所以既满足排序,又用于查找行,因此,如果可能,设计索引应该尽可能同时满足这两种任务,这样是最好的。

只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySQL才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引来做排序。ORDER BY子句和查找型查询的限制是一样的,需要满足最左前缀的要求。

9 压缩(前缀压缩)索引

MyISAM使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存中,这在某些情况下能极大地提高性能。压缩块使用更少的空间,代价是某些操作可能更慢。因为每个值的压缩前缀都依赖前面的值,所以MyISAM查找时无法在索引块使用二分查找而只能从头开始扫描。

10 冗余和重复索引

应避免,因为MySQL需要单独维护重复的索引,并且优化器在优化查询的时候也需要逐个地进行考虑,这会影响性能。

11 索引案例学习

  • 1 支持多种过滤条件
    考虑使用频率,考虑字段选择性,创建不同的组合索引,适用不同的查询条件。
    可以在索引中加入更多的列,并通过IN()的方式覆盖那些WHERE子句中的列。但这种技巧也不能滥用,否则可能会带来麻烦。因为每额外增加一个in条件,优化器需要做的组合都将以指数形式增加。


    高性能的索引策略【高性能mysql第三版笔记】_第8张图片
    image.png
  • 2 避免多个范围条件


    高性能的索引策略【高性能mysql第三版笔记】_第9张图片
    image.png

    高性能的索引策略【高性能mysql第三版笔记】_第10张图片
    image.png

    高性能的索引策略【高性能mysql第三版笔记】_第11张图片
    image.png
  • 3 优化排序
    对于那些选择性非常低的列,可以增加一些特殊的索引来做排序。


    高性能的索引策略【高性能mysql第三版笔记】_第12张图片
    image.png

你可能感兴趣的:(高性能的索引策略【高性能mysql第三版笔记】)