《高性能MySQL》第五章 创建高性能的索引

索引(Key)是存储引擎用于快速找到记录的一种数据结构,这个是索引的基本功能,当然,它还有一些其他有用的属性。

5.1 索引基础

select first_name from sakila.actor where actor_id=5;

如果在actor_id列上建有索引,则mysql将使用索引找到actor_id为5的行,mysql现在索引上按值查找,然后返回所有包含该数值的行。

mysql只能高效地使用索引的最左前缀列,如果一个包含两个列的索引,会不一样的。

使用ORM的时候,很难生成适合索引的查询,除了根据主键查询外。

5.1.1 索引的类型

在Mysq中,索引是在存储引擎层二不是服务器层实现得,所以没有统一的索引标准。

B-Tree索引
实际上很多都是使用b+树,也就是每一个叶子节点都包含指向下一个叶子节点的指针,方便遍历。

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

《高性能MySQL》第五章 创建高性能的索引
这个数据结构特点很容易理解,就是沿用了平衡二叉树的思想,但是分成多叉树,但是如何分裂如何合并动态查找的实现,略有复杂。

定义索引时的列很重要,当某个值相等时,比较下一列。

《高性能MySQL》第五章 创建高性能的索引
全值匹配就是所有条件都匹配(全列)
匹配最左前缀(就是值用索引的第一列)
匹配列前缀(值匹配某一列的值得开头部分)例如查找J开头的人
匹配范围值(Allen-barrmore)
精确匹配某一列并范围匹配另外一列。

只访问索引的查询。

B-tree索引的限制:

  • 如果不是按照索引最左列开始查找的话(姓),就无法使用索引。
  • 不能跳过索引中的列。要从左开始
  • 如果查询中有某个列范围查询,其右边所有列都无法使用索引优化查找。

哈希索引
哈希索引是基于哈希表实现,只有精确匹配索引所有列查询才有效。
《高性能MySQL》第五章 创建高性能的索引
其实在计算机网络中路由表呀,mac地址表呀 各种表也是用了哈希的思想,先记录下每个经过或者来的人的目的地和来源地。

哈希也有它的限制:

  • 哈希索引只包含哈希值和航指针,不存储字段值。
  • 哈希索引不不是按照索引值顺序存储的,所以无法排序。
  • 哈希索引也不支持部分索引匹配查找。
  • 哈希索引值支持等值比较查询,大于小于等范围查询时不支持的
  • 哈希索引的数据非常快,除非有很多哈希冲突。当出现哈希的时候,存储引擎必须遍历链表中的所有航指针,逐行比较,直到符合的条件。
  • 如果哈希冲突比较多的话,一些索引维护操作代价也会很高。

NDB集群引擎和Memory引擎是唯一支持哈希索引的。InnoDB有一个自适应哈希所以,当注意某些索引值使用得非常频繁时,在简历哈希索引。

也可以模拟上述方法自建哈希表。

空间数据索引R-tree

全文索引是查找文本中的关键词,如倒排索引。

其他索引类别

5.2 索引的优点

索引可以让服务器快速定位到表的指定位置。最常见的b-tree索引,所以mysql可以用来做order by操作和group by操作。
1、索引大大减少了服务器需要扫描的数据量
2、索引可以帮助服务器避免排序和临时表
3、索引可以将随机IO变为顺序IO

《高性能MySQL》第五章 创建高性能的索引

5.3 高性能索引策略

5.3.1 独立的列

《高性能MySQL》第五章 创建高性能的索引

5.3.2 前缀索引和索引选择性

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引《高性能MySQL》第五章 创建高性能的索引

5.3.3 多列索引

很多人对索引的理解不够,认为为每个列创建独立的索引就是做好的。

《高性能MySQL》第五章 创建高性能的索引

5.3.4 选择合适的索引列顺序

《高性能MySQL》第五章 创建高性能的索引
顺序与数量与表中数据分布

5.3.5 聚簇索引

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

5.3.6 覆盖索引

如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引。
当一条查询语句符合覆盖索引条件时,sql只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。
使用覆盖索引Innodb比MyISAM效果更好----InnoDB使用聚集索引组织数据,如果二级索引中包含查询所需的数据,就不再需要在聚集索引中查找了
注:遇到以下情况,执行计划不会选择覆盖查询
1.select选择的字段中含有不在索引中的字段 ,即索引没有覆盖全部的列。
2.where条件中不能含有对索引进行like的操作。

《高性能MySQL》第五章 创建高性能的索引

5.3.7 使用索引扫描来做排序

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

5.3.8 压缩索引(前缀压缩)

MyISAM使用前缀压缩来减少索引大小,从而让更多的索引放入内存。

《高性能MySQL》第五章 创建高性能的索引

5.3.9 冗余和重复索引

《高性能MySQL》第五章 创建高性能的索引

5.3.10 未使用的索引

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

5.3.11 索引和锁

《高性能MySQL》第五章 创建高性能的索引

5.4 索引案例学习

《高性能MySQL》第五章 创建高性能的索引

5.4.1 支持多种过滤条件

1、查看where字句中最平凡的列。(使用频率简历索引)
《高性能MySQL》第五章 创建高性能的索引

5.4.2 避免多个范围条件

《高性能MySQL》第五章 创建高性能的索引
将范围转化为等值查询

5.4.3 优化排序

《高性能MySQL》第五章 创建高性能的索引

5.5 维护索引和表

维护表有3个目的:1、找到并修复坏的表2、维护准确的索引3、减少碎片

5.5.1 找到并修复损坏的表

《高性能MySQL》第五章 创建高性能的索引

5.5.2 更新索引统计信息

《高性能MySQL》第五章 创建高性能的索引

5.5.3 减少索引和数据碎片

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

5.6 总结

《高性能MySQL》第五章 创建高性能的索引
《高性能MySQL》第五章 创建高性能的索引

《高性能MySQL》第五章 创建高性能的索引