MYSQL—索引总结(上)

 索引是什么

索引在(在mysql中也叫做键(key))是存储引擎用于快速找到记录的一种数据结构。

索引的类型:

索引有很多种类型,

B-TREE 索引 

能够加速访问数据的速度,因为存储引擎不再需要进行全表扫描来获取需要的数据,取而代之的是从索引的根节点,开始进行搜索。根节点的槽中存放指向子节点的指针,存储引擎根据这些指针向下层查找。

B-Tree 对索引的列是顺序组织存储的,所以很适合查找范围数据。

B-Tree 索引试用于全键值、键值范围或者键前缀查找。

因为索引树中的节点是有序的,所以除了按值查找之外,索引还可以用于查询中的order by 操作(按顺序查找)

InnoDB使用的是B+Tree数据结构。B+Tree 数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。

哈希索引

哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),哈希码是有一个较小的值,并且不同的键值的行计算出来的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。

哈希索引的限制:

哈希索引只包含哈希值和行指针,而不存储字段值,所以不能哟个索引中的值来避免读取行。

哈希索引的数据并不是按照索引值顺序存储的,所以也就无法用于排序。

哈希索引也不支持部分索引列匹配查找。因为哈希索引始终是使用索引列的全部内容来计算哈希值的。

哈希索引只支持等值比较查询  包括 =、in()<=>,不支持范围查询。

空间数据索引(R-Tree)

myISAM 表支持空间索引,可以用作地理数据存储。空间索引会从所有维度来索引数据。

全文索引

全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是比较比较索引中的值。全文搜索和其他几类索引的匹配方式完全不一样。在相同的裂伤同事创建全文索引和基于值的B-Tree 索引不会有冲突。

其他索引类别:TokuDB 使用分型树索引(fractal tree index),这是一类较新开发的数据结构。感兴趣自己去找资料。

索引的优点:

1 索引打打减少了服务器需要扫描的数据量

2 索引可以帮助服务器避免排序和临时表

3 索引可以将随机I/O变为顺序I/O

前缀和索引的选择性:

有时候需要索引很长的字符列,这会让索引变得大且慢。通常可以索引开的部分字符,这样可以大大节约索引空间,从而提高索引效率。但是这样会降低索引的选择性。

索引的选择性是指:不重复的索引值(基数)和数据表的记录总数(#T)的比值,范围从1/#T到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让mysql在查找时候过滤掉更多的行。

有个公式可以来计算一下索引的选择性

先计算完整列的选择性

select count(distinct city)/ count(*) from table.city; //假设是0.0312

那么如果索引的选择性,能够接近这个数字基本上就可以用了。

索引选择性计算的公式:

select count(distinct left(city,4))/count(*) from table.city 逐渐增加left函数的数值,观察得到的数字。

前缀索引是一种能是索引更小,更快的方法,但是灵一方面也有其缺点:

mysql 无法使用前缀索引做order by 和group by 也无法使用前缀索引做覆盖扫描。

索引列顺序:

 正确的顺序依赖于使用该索引的查询,并且同事需要考虑如何更好的满足排序和分组需要。

经验法则:当不要考虑排序和分组时,将选择性最高的列放到索引最前列。

sarg (search argument)查询预测:

select * from payment where staff_id=2 and customer_id=584;

这个sql如何建立索引呢,

select sum(staff_id=2),sum(customer_id=584) from payment;

sum(staff_2):7992行

sum(customer_id=584):30行

所以根据经验法则将customer_id 放前面。

聚簇索引:

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。innodb的聚簇索引实际上在同一个结构中保存了B-Tree 索引和数据行。

当表有聚簇索引时,它的数据行实际上存放在索引的叶子页(leaf page)中。术语“聚簇”表示数据行和相邻的键值紧凑的存储在一起。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。由于 索引在引擎层而不是服务器层实现,因此不是所有的存储引擎都支持聚簇索引。

innodb 通过主键聚集数据,如果没有定义主键,Innodb 会选择一个唯一的非空索引代替。如果没有这样的索引,innodb会隐式的定义一个主键(rowid)来作为聚簇索引。

聚集数据的优点:

可以把相关的数据保存在一起

数据访问更快。聚簇索引把索引和数据保存在同一个B-Tree中,因此从聚簇索引中获取数据通常比在费举出索引中查找要快

使用覆盖索引扫描的查询可以直接使用页节点中的主键值。

缺点:页分裂。会导致表占用更多的磁盘空间。

     二级索引访问需要两次索引查找。二级索引叶子节点保存的不是指向行的物理位置的指针,而是行的主键值。先根据二级索引找到找到主键,再去聚簇索引中查找到对应的行。解决方案是:自适应哈希索引。

自增主键:

如过不使用自增主键有可能会有以下缺点。

写入的目标页肯跟已经刷到磁盘上并从缓存中移除,或者是还没有被加载到缓存中,InnoDB在插入之前不不得不先找到并从磁盘读取目标页到内存中。这将导致大量的随机I/O;

因为写是乱序的,InnoDB不得不频繁地做也页分裂操作,以便新的行分配空间。页分裂会导致移动大量数据,一次插入最少需要修改三个页而不是一个页

由于频繁的页分裂,页会变的系数并被不规则的填充,所以最终数据会有碎片。

用自增主键,做一次OPTIMIZE TABLE来重建表并优化页的填充。

辅助索引(secondary index)

表中除了聚集索引外其他索引都是辅助索引(Secondary Index,也称为非聚集索引)(unique key啊、index key啊),

与聚集索引的区别是:

辅助索引的叶子节点不包含行记录的全部数据,只包含指向数据行的指针。

辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引。

Innodb的辅助索引里面存放的是主键的值,而不是指向行的物理位置。

myISAM的辅助索引里面存储的是数据的地址,用这个地址的值来找数据记录。

覆盖索引:

mysql 可以使用索引来直接获取列的数据,这样就需要再读取数据行。如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢?如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为覆盖索引。

不是所有的类型索引都可以成为覆盖索引,它必须要存储索引列的值,而哈希,空间,全文索引都不存储索引列的值,所以MYSQL只能使用B-Tree 索引做覆盖索引。当一个被索引覆盖的查询时,explain的Extra列可以看到 Using index的信息。

1 索引为什么越短越好

2 索引失效的场景是什么

3 聚簇索引和非聚簇索引是什么 有什么区别

4 索引下推是什么

5 最左前缀原则是什么

6 回表是什么

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注