1、什么是索引
索引(也成为“键”)是存储引擎用于快速找到记录的一种数据结构。
索引对于良好的性能非常关键。尤其是当表中数据量越来越大时,索引对于性能的影响愈发重要。数据量小且负载低时,不恰当的索引对性能的影响可能不够明显,但是当数据量主键增大是,性能会急剧下降。
索引可以包含一个列或多个列的值。如果同一索引包含多个列,那么列的顺序十分重要,因为MySQL只能高效使用索引的左前缀列。
2、索引的类型
索引有很多类型,可以为不同场景提供更好的性能。在MySQL中,索引是在存储引擎层而不是服务器层实现的。所以并没有统一的索引标准:不同存储引擎的索引的工作方式不一样,也不是所有的存储引擎都支持所有类型的索引。即使多个存储引擎支持同一类型的索引,其底层实现也可能不相同。
B-Tree索引
大多数MySQL引擎都支持这种索引。存储引擎InnoDB使用的索引类型是B+Tree(B-Tree的变体)。下图为建立在B-Tree结构的索引(从技术上来说是B+Tree)上的索引
B-Tree 索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取需要的数据,取而代之的是从索引的根节点开始进行搜索。根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下层进行查找。通过比较节点页的值和要查找的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点页中指的上限和下限最终存储引擎要么是找到对应的值,要么该记录不存在。
树的深度和表的大小直接相关。B-Tree对索引列是顺序组织存储的,所以很适合查找范围数据。
全值匹配:全值匹配指的是索引中的所有列进行匹配。
匹配最左前缀:只使用索引的第一列。
匹配列前缀:也可以匹配某一列的值的开头部分。
匹配范围值:匹配在两个值之间或之外的数据。
精确匹配某一列并范围匹配另外一列:某些索引精确匹配到某一列,并且另一个索引匹配范围值。
B-Tree通常可以支持“只访问索引的查询”,即查询只需要访问索引,而无需访问数据行。、
B-Tree索引的限制:
- 如果不是按照索引最左列开始查找,则无法使用索引。
- 不能跳出索引中的列
- 如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。
这些限制都和索引的顺序有关。在优化性能的时候,可能需要使用相同的列但顺序不同的索引来满足不同类型的查询需求。
哈希索引
哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的数值,并且不同键值的行计算出的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
在MySQL中只有Memory引擎支持哈希索引。哈希索引是Memory默认的索引类型,Memory引擎同时也支持B-Tree索引。Memory引擎是支持非唯一哈希索引的,这在数据库世界里是比较与众不同的。如果多个列的哈希值相同,索引会以链表的方式存放在多个记录指针到同一个哈希条目中。
哈希索引的限制:
- 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况这一点对性能的影响并不明显。
- 哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序。
- 哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。例如:如果数据列(A,B)上建立哈希索引,如果查询到数据只有A列,则无法使用该索引。
- 哈希索引只支持等值比较查询,包括=、IN、(注意<=>和<>是不同的操作)。也不支持任何范围查询。
- 范文哈希索引的数据非常快,除非有很多哈希冲突(不同的索引列值却有可能有相同的哈希值。)。当出现哈西冲突的时候,存储引擎必须遍历链表中所有行指针,逐行进行比较,直到找到所有符合条件的行。
- 如果哈希冲突很多的话,一些索引维护操作的代价也会很高。例如:如果在某个选择性很低(哈希冲突很多)的列上建立哈希索引,那么从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越多,代价越大。
未完待续。。。。。。。