0%

Database Index

MySql索引相关内容。

索引类型

在MySql中,索引是在存储引擎层而不是服务器层实现的。

B Tree/B+ Tree

索引对多个值进行排序的依据是CREATE TABLE语句中定义索引时的顺序。

适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。

索引对如下类型查询有效: + 全值匹配:和索引中的所有列进行匹配; + 匹配最左前缀:只使用索引前几列; + 匹配列前缀:匹配某一列的值的开头部分; + 匹配范围值:查找第一列在某一范围内的值; + 精确匹配某一列并范围匹配另外一列:匹配第一列以及第二列前缀为指定的查找。

限制: + 如果不是按照索引的最左列开始查找,则无法使用索引; + 不能跳过索引中的列; + 若查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找;

哈希索引(hash index)

只有精确匹配索引所有列的查询才有效。

限制: + 哈希索引只包含哈希值和行指针,而不存储字段值; + 哈希索引数据并不是按照索引值顺序存储的,所以无法用于排序; + 不支持部分索引列匹配查找。 + 只支持等值比较查询,包括=,IN() + 哈希冲突很多的话,索引维护操作的代价会很高(如删除操作)。

空间数据索引(R-TREE)

空间索引会从所有维度来索引数据。 + 可以使用任意维度类组合查询 必须使用MySql的GIS相关函数来维护数据,而MySql的GIS支持并不完善,所以大部分人都不会使用这个特性。

全文索引

查找文本中的关键字,而不是直接比较索引中的值。 需要注意细节:停用词、词干和复数、布尔搜索等。

全文索引通常使用倒排索引(inverted index)来实现。通常利用关联数组实现存储单词与单词滋生在一个或多个文档中所在位置之间的映射。如: + inverted file index, 表现为{单词,单词所在文档ID} + full inverted index, 表现为{单词,(单词所在文档的ID,在具体文档中的位置)}

MySql中用法示例:select * from example match(column1) against ('find' in natural language mode) >具体用法见 MySql技术内幕 P240

其他索引类别

TokuDB:分形树索引(fractal tree index) InnoDB:聚簇索引、覆盖索引

索引优点

  • 大大减少了服务器需要扫描的数据量;
  • 帮助服务器避免排序和临时表;
  • 将随机I/O变为顺序I/O。

索引策略

独立的列

索引列不能是表达式的一部分,也不能是函数的参数。 如select actor_id from actor where actor_id+1=5 >养成将索引列单独放在比较符号一侧的习惯

前缀索引和索引选择性

对于索引较长的情况,可以索引开始的部分字符,这样可以节约索引空间,提高索引效率,但是会降低索引的选择性 对于BLOB、TEXT或者很长的VARCHAR类型的列,必须使用前缀索引,因为MySql不允许索引这些列的完整长度。 需要选择足够长的前缀保证较高的选择性。

多列索引

为每个列创建独立的索引或者按照错误的顺序创建多列索引,得不到好的效果。

合适的索引列顺序

针对B-TREE索引。
原则: + 在不需要考虑排序和分组时,将选择性最高的列放到索引最前列;

聚簇索引

不是一种单独的索引类型,而是一种数据存储方式。(如同一个结构中保存了B-TREE索引和数据行); 一个表只能有一个聚簇索引。 优点: + 可以把相关的数据保存在一起; + 数据访问更快; + 使用覆盖索引扫描的查询可以直接使用页节点中的主键值。

缺点: + 若数据都在内存中,则访问的顺序就没这么重要了,聚簇索引也就没什么优势; + 插入速度依赖于插入顺序,(按主键的顺序) + 更新聚簇索引的代价很高; + 插入新行或者更新主键时,可能导致页分裂; + 可能导致全表扫描变慢,尤其是行比较稀疏时; + 二级索引访问需要两次索引查找。(二级索引保存的行指针保存的不是指向行的物理位置指针,而是行的主键值)

覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,称为覆盖索引。即只需要扫描索引无须回表。 优点: + 只需要访问索引,可以极大的减少数据访问量; + 因为索引是按照列值顺序存储的,所以范围查询的I/O次数会少很多; + 一些存储引擎的数据依赖于操作系统缓存,因此访问数据需要一次系统调用。覆盖查询可以避免; + 如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。

MySql不能在索引中执行LIKE操作。 MySql能在索引中做最左前缀匹配的LIKE比较,但是如果是通配符开头的LIKE查询,存储引擎无法做比较查询。

使用索引扫描来做排序

只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySql才能使用索引来对结果做排序。

[===============]

[1] 高性能MySql 第三版 [2] MySql技术内幕 InnoDB存储引擎 第二版