Mysql索引基础:
1. 索引基本概念****
 索引在Mysql中也称为键(key),是存储引擎用于快速找到记录的一种数据结构。类似书的目录。
 索引可以包含一个或多个列的值,如果包含多个列的值,那么列的顺序也非常重要,因为Mysql只能高效的使用索引的最左前缀列。

索引的类型:
 B-Tree索引:
Part1:基本概念
 InnoDB使用的就是B+Tree
 B-Tree意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同
 B-Tree之所以能加快访问数据的速度,是因为存储引擎不需要进行全表扫描来获得数据,取而代之的是从索引的根节点开始进行搜索,类似数据结构中B+tree的查找。
 叶子节点比较特殊,他们的指针指向的是被索引的数据,而不是节点页,叶子结点之间也有指针连接

Part2:可以使用B-Tree索引的查询类型:适用于全键值,键值范围或键前缀查找,其中键前缀查找只适用于根据最左前缀的查找,包括以下方面:

全值匹配:匹配索引中包含的所有列,如图2中的:姓名+出生日期
匹配最左前缀:只使用索引的第一列,比如图2中索引的last-name,查找所有姓为Allen的人
匹配列前缀:使用某一列值得开头部分,比如以J开头的姓名的人
 匹配范围值:查找姓名在Allen和Barrymore之间的人,这里只使用了索引的第一列
精准匹配某一列并范围匹配另一列:例如第一列last_name全匹配,第二列first_name范围匹配
只访问索引的查询:B-tree通常可以支持“只访问索引的查询”,即查询只需要访问索引,无需访问数据行

Part3:B-Tree索引的限制
如果不是按照索引的最左列开始查找,则无法使用索引。例如图中的例子,无法查找名字为Bill的人,也无法查找某个特定生日的人,因为这两列都不是最左数据列
不能跳过索引的列:即必须按指定顺序查找,不能只指定last_name和出生日期而不指定(first_name),这样的话,Mysql只能使用索引的第一列last_name;
如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引优化查询(如果三列索引查询中的第二列是一个范围查询,例如like,则第三列索引在这个查询中就失效了,无法被使用,但可以用来作为其他目的的查询)
结论:索引的顺序非常重要
图例:假设有如下的数据表,则索引表形式如图所示
Mysql索引基础知识总结
Mysql索引基础知识总结Mysql索引基础知识总结

 哈希索引
Part1 基本概念
 Hash索引基于hash表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个hash码,hash码是一个较小的值,并且不同的键值计算出来的数值也不一样。Hash索引将所有的哈希码存储在索引中,同时保存指向每个数据行的指针。
 在Mysql中,只有Memory引擎支持哈希索引,也是Memory的默认索引类型,他也支持非唯一hash索引。如果多个列的哈希值相同,索引会以链表的形式存放多个记录指针到同一个哈希条目中。
 NDB集群引擎也支持唯一哈希索引
 InnoDB有一个特殊功能:自适应哈希索引:在B-Tree基础上再创建一个哈希索引,这样就更快了,是自主行为,用户无法控制,但可以关闭。
 Hash查找的三个步骤:1 计算键值的hash码 2 使用该码找到记录指针 3 比较指针所指的值是否为要查找的值,完成查找
举个栗子:
Mysql索引基础知识总结
Part2:Hash索引的优缺点
 优点:索引只存储对应的哈希值,所以索引的结构十分紧凑,查找速度非常快
缺点:
 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行,不过访问内存中的行速度很快,影响并不大。(我认为这个影响的是第三步,对比那一步)
 无法对索引进行排序:数据不是按照索引值顺存储的,指针指到哪就是哪儿
 不支持部分索引匹配查找:索引是用多个 索引列的内容来计算处一个hash索引值,所以只有给处 所有的索引值,才能找到对应的hash码
 哈希索引只支持等值比较查询,也不支持任何范围查询
 容易出现哈希冲突:出现哈希冲突的时候,存储引擎必须比遍历链表的所有行指针,逐条比较
 如果哈希冲突很多的话,一些索引维护的代价也很高。

注:如果要存储大量的URL,并需要根据URL来进行搜索查找,如果使用B-tree来存储,存储内容就会很大,因为URL很长,如何解决
答:可以创建自定义哈希索引,先删除原来URL列上的索引,新增一个被索引的列,这个列的内容为URL的哈希码值,这样底层的查询还是通过B-Tree,但查询键的内容不再是很长的URL,而是URL对应的哈希码值,这样更快。但是这样做的缺陷是需要维护哈希值,可以手动维护,也可以触发器实现;
如何处理哈希冲突:当数据过大时,很容易出现哈希冲突,例如执行语句的where中只选择哈希码,可能会查出多组数据,因此为了避免哈希冲突,应该在where子句中加入列值,即URL的原值,这样在哈希码相同的情况下,可以通过对比URL的值进行查找,避免哈希冲突。

2. 高性能的索引策略
 独立的列
独立的列是指索引列不能是表达式的一部分,也不能是函数的参数,不然可能无法使用索引
 前缀索引和索引选择性
有时候需要索引很长的字符列,这会让索引变得大且慢,除了前面的模拟哈希索引外,还可以使用前缀索引,诀窍在于选择足够长的前缀以保证较高的选择性,同时不能太长。
 多列索引
会出现“索引合并”,出现这种情况一般来说是索引建立的很糟糕
 选择合适的索引列顺序
 聚簇索引
把数据和索引放在一起的方式叫做聚簇索引,因为数据和索引在一起,查到了索引就查到了数据,和聚簇索引相对应的叫做非聚簇索引,也叫做二次索引,我们一般的索引都是二次索引,索引里面存放的是主键id,需要通过主键id去二次查找。一个表只能有一个聚簇索引,并且只能建立在唯一字段上,一般都是主键列。
InnoDB 都是用聚簇索引方式来存储数据的。在有主键的时候,聚簇索引列是主键,没有主键的时候会自动选择一个唯一字段,如果唯一字段都没有,那么会自动维护一个唯一字段作为聚簇索引。因为 聚簇索引直接存放数据,所以聚簇索引列比别的索引快(避免了二次查找)。所以有一种说法叫做,innoDB里面主键列是最快的索引列,就是因为主键列会自动建立聚簇索引。
建议参考:https://baike.baidu.com/reference/11041381/ef5coESVNrkaxlvL4q63bdhPARf0AgaCMF0Px31zvdhzNwuyKZmqiOmEkHXbxVhkktjgIinnY8HHNTUecouQukEB0XoXWy-5lvtzlmAVhANP9fE
 覆盖索引
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。
不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引列的值,而哈希索引,空间所引和全文索引等都不存储索引列的值,所以Mysql只能使用B-tree索引做覆盖索引

相关文章:

  • 2021-12-22
  • 2022-01-03
  • 2021-10-27
  • 2021-10-01
  • 2021-12-07
  • 2021-10-03
  • 2021-12-09
猜你喜欢
  • 2021-09-25
  • 2021-11-02
  • 2021-11-08
  • 2021-11-06
  • 2021-12-08
  • 2019-12-17
  • 2021-11-21
  • 2021-12-13
相关资源
相似解决方案