CSDN|别再一知半解啦,索引其实就这么回事!( 三 )


加速查询 + 列值唯一(可以有null)
ALTER TABLE 'table_name' ADD UNIQUE index_name('col');普通索引用表中的普通列构建的索引 , 没有任何限制 。
仅加速查询
ALTER TABLE 'table_name' ADD INDEX index_name('col');全文索引用大文本对象的列构建的索引
ALTER TABLE 'table_name' ADD FULLTEXT INDEX ft_index('col');组合索引用多个列组合构建的索引 , 这多个列中的值不允许有空值 。
多列值组成一个索引 , 专门用于组合搜索 , 其效率大于索引合并 。
ALTER TABLE 'table_name' ADD INDEX index_name('col1','col2','col3');在对多列组合建立索引时 , 会遵循「最左前缀」原则 。
最左前缀原则:顾名思义 , 就是最左优先 , 上例中我们创建了 (col1, col2, col3) 多列索引,相当于创建了 (col1) 单列索引 , (col1, col2) 组合索引以及 (col1, col2, col3) 组合索引 。
所以当我们在创建多列索引时 , 要根据业务场景 , 将 where 子句中使用最频繁的一列放在最左边 。
空间索引对空间数据类型的字段建立的索引 , 底层可通过 R 树实现 。 只不过使用较少 , 了解即可 。
实现原理我们知道 , 索引的底层本身就是通过数据结构来进行实现的 。 那么根据其底层的结构 , 常见的索引类型可分为哈希索引 , BTree 索引 , B+Tree 索引等 。 这里我们就主要来介绍这三种索引背后的实现机制 。
哈希索引顾名思义 , 哈希索引是通过哈希表实现的 。 哈希表的特点在之前的文章「九大数据结构」中已经详细介绍过 。 通过哈希表的键值之间的对应关系 , 能够在查询时精确匹配索引的所有列 。 哈希索引将所有的根据索引列计算出来的哈希码存储在索引中 , 同时将指向每个数据行的指针保存在哈希表中 。


CSDN|别再一知半解啦,索引其实就这么回事!
本文插图
上图是通过哈希索引查询行数据的示意图 , 可以发现哈希索引同样会发生哈希冲突 , 并且是通过链地址法解决冲突的 。 当发送冲突时 , 还需要对链表进行遍历对比 , 才能够找到最终的结果 。
在 MySQL 中 , 只有 Memory 存储引擎显式的支持哈希索引 , 而innodb是隐式支持哈希索引的 。
这里的隐式支持是指 , innodb引擎有一个特殊的功能 “自适应哈希索引” , 当innodb注意到一些索引值被使用的非常频繁时 , 且符合哈希特点(如每次查询的列都一样) , 它会在内存中基于 B-Tree 索引之上再创建一个哈希索引 。 这样就让 BTree 索引也具有哈希索引的一些有点 。 这是一个完全自动的、内部的行为 。
由于哈希结构的特殊性 , 其用于非常高的检索效率 , 通过哈希函数的映射可以一步到位 。 但是同样也是因为结构的特殊 , 导致哈希索引只适用于某些特定的场合 。 哈希索引的限制[1]:
  1. 不支持范围查询 , 比如 WHERE a > 5;只支持等值比较查询 , 包括=、IN 、<=>
  2. 无法被用来避免数据的排序操作;因为经过了哈希函数的映射过程 , 使得丢失了哈希前后的大小关系 , 从而无法按照索引值的顺序存储 。
  3. 不支持部分索引列的匹配查找 , 因为哈希索引始终使用索引列的全部内容来计算哈希值 。 例如在数据列 (A, B) 上建立哈希索引 , 如果查询只有数据列 A , 则无法使用该索引 。
  4. 无法避免表扫描 。 因为当出现哈希冲突的时候 , 存储引擎必须遍历链表(拉链法)中所有的行指针 , 逐行进行比较 , 直到找到所有符合条件的行 。
  5. 哈希冲突很多的情况下 , 其索引维护的代价很高 , 并且性能并不一定会比 BTree 索引高 。
BTree 索引BTree 实际上是一颗多叉平衡搜索树 。 从名字可以看出 , BTree 首先是一颗多叉搜索树 , 这意味着它是具有顺序的;其次 BTree 还是平衡的 , 这意味着它的左右子树高度差小于等于1 。


推荐阅读