vlambda博客
学习文章列表

MySql读书笔记-索引

B+树高度一般在2-4层,也就是查找某一键值的行记录最多需要2-4次IO意味着只需0.02-0.04s

聚集索引和辅助索引不同的是,叶子节点存放的是否是一整行的信息

MySql读书笔记-索引


一:聚集索引:搜索范围

InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放。

聚集索引是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚集索引的叶子节点成为数据页。

同B+树数据结构一样,每个数据页都通过一个双向链表进行链接。


实际数据页只能按照一颗树进行排序,因此每张表只能拥有一个聚集索引。

多数情况,查询优化器倾向于采用聚集索引。--因为聚集索引能够在树索引的叶子节点上直接找到数据。此外,由于定义了数据的逻辑顺序,聚集索引能够特别快的访问针对范围值得查询。


查询优化器能够快速发现某一段范围的数据也需要扫描

聚集索引的存储并不是物理上联系的,而是逻辑上连续的。

  • 页通过双向链表链接,页按照逐渐的顺序排序;

  • 每个页中记录也是双线链表进行维护的,物理存储上可以同样不按照主键存储;

如果按照顺序物理的存储数据,维护成本高

另一个好处是,对于逐渐的排序查找和范围查找速度非常快。

叶子节点发数据就是用户所要查询的数据。

范围查询,如果查找主键某一范围的数据,通过叶子节点的上层中间节点就可以得到页的范围,之后直接读取数据页即可。


二:辅助索引

也称为非聚集索引,叶子节点不包含行记录的全部数据

叶子节点除了包含键值以外,每个叶子节点中索引行中还包含一个书签。书签告诉InnoDB存储引擎哪里可以找到索引对应的行数据。

因为引擎表是索引组织表,因此辅助索引的书签就是相应行数据的聚集索引键。


辅助索引的存在不影响数据在聚集索引的组织,因此每张表上可以有多个辅助索引。当辅助索引来寻找数据时,引擎会遍历副主索引并通过叶级别的指针获得指向主键索引的主键,然后通过主键索引找到完成的行记录。


理解:

字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。

使用

OLTP应用中,查询只从数据库中取得小部分数据,一般可能在10条记录一下,甚至很多时候只取1条记录,根据主键查用户信息,订单号查订单信息,这是典型的OLTP应用查询语句。

在这种情况下, B+树索引建立后,对该索引的使用应该只是通过该索引取得表中少部分数据。这时候建立B+索引才是有意义的,否则即使建立了,优化器也可能选择不适用索引。

OLAP应用,需要访问表中大量的数据,这些查询多是面向分析的查询,对于OLAP中复杂查询,要涉及多张表之间的联接操作。

因此索引的添加仍然是有意义的,通常会需要对时间字段进行索引,因为多数统计是根据时间维度进行数据筛选。


三:什么是Cardinality?

什么时候添加B+树索引,一般经验是,在访问表中很少一部分时使用B+树索引才有意义,

对于性别字段、地区、类型字段,取值范围小,称为低选择性。这时选择B+树是没有必要的。

字段的取值范围很广几乎没有重复,即属于高选择性,使用B+树是适合的,例如姓名字段

怎么看索引是否具有高选择性呢?通过show index 结果列Cardinality观察,值表示索引中不重复记录数量的预估值。---不是准确值

数据库对于Cardinality统计是通过采样的方式完成的,统计信息的更新发生在两个操作:insert和update。不可能每次操作就去更新,这样会增加数据库系统的符合,对于大表的统计,时间上也不允许数据库这样操作。


四:B+树索引的使用

4.1 联合索引


指对表上的多个列进行索引,联合索引的创建方法与单个索引创建的方法一样,不同的在于多个索引列也是B+树,不同的是联合索引的键值的数量不是1是大于等于2。

联合索引,键值也是排序的,通过叶子节点可以逻辑上顺序读出所有数据

联合索引已经对第二个键值进行了顺序处理。

4.2 覆盖索引

从辅助索引中既可以得到查询的记录,不需要查询聚集索引中的记录。

覆盖索引的好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。

4.3 优化器选择不使用索引的情况

用户要选取数据是整行的信息,使用辅助索引查询到指定顺序后,还需要再一次进行术前查找的数据则是无顺序的,因此变成了磁盘上的离散读操作。

如果要求访问的数据量小,优化器还是会选择辅助索引,但是访问的数据占整个表中数据大部分的时候(20%左右),优化器会选择通过聚集索引来查找数据。

因此对于不能索引覆盖的情况,优化器选择辅助索引的情况是,通过辅助索引查找的数据是少量的。用户使用的磁盘是固态硬盘,随机读操作常使用 force index来强制使用某个索引。

索引提示

优化器错误选择索引

sql可以选择的索引非常多

select * from t USE INDEX(a) where a = 1 and b = 2  优化器还是会根据自己判断选择

select * from t FORCE INDEX(a) where a = 1 and b = 2 可靠

Multi-Range Read优化

目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问。

适用于 range,ref,eq_ref类型的查询

工作方式

将查询到的辅助索引存在于缓存中,缓存中的数据是根据辅助索引键值排序的。

将缓存中的键值根据RowID进行排序

将RowID的排序顺序来访问实际的数据文件

五:哈希算法

散列表,由直接寻址改进而来。链接法解决碰撞问题

InnoDB存储引擎使用哈希算法对字典进行查找,链表的方式解决冲突,哈希函数使用除法散列方式。

问:为什么不都用哈希索引?

  1. 哈希索引仅能满足“= ,in,<=>”插叙,不能范围查询;

  2. 哈希索引无法被用来避免数据的排序操作;

  3. 哈希索引不能用部分索引查询,即不支持最左匹配规则-因为联合索引是将索引键合并后一起计算hash值的

  4. 哈希索引任何时候都不能避免表扫描;

  5. 哈希索引遇到大量hash值相等的情况性能并不一定比B+树索引高

  6. 哈希索引不能进行like这样的模糊查询


哈希索引在等值查询没有范围查询没有排序的场景适合使用。