MySQL学习笔记——索引的理解

索引的概念

  • 什么叫索引

    索引也称作键,是存储引擎用于快速找到记录的一种数据结构。索引可以加快查询速度,原因是索引使用特定的数据结构(B-Tree)对特定的列额外组织存放,加快存储引擎(索引是存储引擎实现)查找记录的速度。

B树和B+树之间的区别

  • B树的数据结构: avatar
  • B+树和B树的区别

    1、有n棵子树的结点中含有n-1个关键字(与B树相同,MySQL中的B+树索引采用这种); (此处有争议,另一种说法是,B+树具有n棵子树的结点中含有n个关键字)

    2、所有的叶子结点中包含了全部关键字的信息,即所有的非叶子节点仅仅起到索引作用,非叶结点中仅含有其子树根结点中最大关键字及指向该子树的指针。(而B树的叶子节点并没有包括全部需要查找的信息)

    3、在B+树上,有一个指针指向关键字最小的叶子节点,所有叶子节点链接成一个线性链表。(B树不存在指针将叶子节点连成一个链表)

  • B树如图所示

avatar

  • B+树如图所示 avatar

索引的优点

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

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

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

高性能的索引策略

  • 独立的列

    独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。例如:SELECT id FROM actor WHERE id+1=5;

    这个例子就不能使用id的索引,可以改成id=4,这就可以使用索引了。 例如另外一种常见错误:SELECT ... WHERE TO_DAYS(CURRENT_DATE)-TO_DAYS(date_col)<=10; 这是不能使用date_col列的索引的。

  • 前缀索引和索引选择性

    有时候需要索引很长的的字符列,这会让索引变得大且慢。这时就可以采用前缀索引,即只索引列的前面一部分字符,这样可以大大节约索引空间,从而提高索引效率。但是这样会降低索引的选择性。索引的选择性是指,不重复的索引值和数据表的记录总数(#T)的比值,范围是在1/#T到1之间。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

  • 多列索引及索引列顺序

    一个常见的错误就是,为每个列创建独立的索引,或者按照错误的顺序创建多列索引。在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能。当出现服务器对多个索引做相交操作时(通常有多个AND条件),通常意味着需要一个包含所有列的多列索引,而不是多个独立的单列索引。

    索引顺序的选择通常是一个令人困惑的问题,正确的顺序依赖于使用该索引的查询,并且同时需要考虑如何更好地满足排序和分组的需求。在一个多列B+树索引中,索引列的顺序意味着索引首先按照最左列进行排序,其次是第二列,等等。选择索引列顺序有一个经验法则:将选择性最高的列放到索引最前列(在不需要考虑排序和分组的时候,效果很好)。

    在选择索引的时候,既要选择足够长的前缀以保证较高的选择性,同时又不能太长,以便节约空间。

聚簇索引

  • 在同一个结构中既存储B+树索引,又存储数据行
  • InnoDB支持聚簇索引,也就是将数据行和相邻的键值紧凑的存储在一起,而MyISAM不支持聚簇索引,也就是将索引文件和数据文件分成两个文件进行存储
  • InnoDB是通过主键聚集数据的,不支持选择其他索引作为聚集索引。

聚簇索引的优点

  • 可以把相关数据保存在一起。你如实现电子邮箱时,可以根据用户ID聚集数据。
  • 数据访问更快。聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比在非聚簇索引中查找更快。
  • 使用索引覆盖扫描的查询可以直接使用叶节点中的主键值。

聚簇索引的缺点

  • 聚簇索引提高了I/O密集型应用的性能,但是如果数据全部都可以放到内存中,那聚簇索引就没有什么优势了。
  • 插入速度严重依赖插入顺序,按主键顺序插入是速度最快的。
  • 更新索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置。而行的移动有可能会导致“页分裂”问题。当某一行必须插入到一个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是页分裂。
  • 聚簇索引可能会导致全表扫描变慢,尤其是行比较稀疏的时候。
  • 二级索引(非聚集索引)可能比想象的要大,因为在二级索引的叶子节点中包含了引用行的主键列。
  • 二级索引访问需要两次查找。存储引擎需要找到二级索引的叶子节点获得对应的主键值,然后根据这个主键值去聚簇索引中查找对应的行。这里进行了两次B+树查找。

非聚簇索引和聚簇索引之间的区别

聚簇索引是指索引文件和数据文件是同一份文件,也就是该索引实现方式中B+Tree的叶子节点上的data是数据本身,而对于B+树或一般索引,data指的是主索引,也就是data不是数据本身,而是数据存放的地址,因此非聚簇索引比聚簇索引多一次I/O操作

MyISAM和InnoDB数据分布

  • MyISAM和InnoDB的数据分布其实就是聚簇索引和非聚簇索引之间的区别
  • MyISAM是非聚簇索引,而InnoDB是聚簇索引
  • InnoDB将通过主键聚集数据,如果没有定义主键,InnoDB会选择一个唯一的非空索引替代
  • 对于MyISAM的主键索引和二级索引没有什么区别
  • 而对于InnoDB由于它是聚簇索引,所以它的主键索引得到的就是整个数据行,而不是存放的对应的行号,同时,对于二级索引,存放的也不是行号,而是保存的行的主键值,所以需要根据这个主键值再进行一次索引,所以需要两次索引查找

覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。覆盖索引能够极大地提高性能。

覆盖索引有许多好处: - 索引条目通常远小于数据行大小,所以如果只需要读取索引,那MySQL就会极大地减少数据访问量。 - 因为索引是按照列值顺序存储的,所以对于I/O密集型的范围查询会比随机从磁盘中读取每一行的I/O要少得多。 - 一些存储引擎如MyISAM只在内存中缓存索引,数据则依赖于操作系统来缓存,因此要访问数据需要一次系统调用,这会导致严重的性能问题。而覆盖索引则只需要访问内存即可。 - 由于InnoDB的聚簇索引,覆盖索引对InnoDB特别有用。如果二级索引能够覆盖查询,则可以避免对主键索引的二次查询。

Note:覆盖索引必须要存储索引列的值,所以,MySQL只能使用B+树做覆盖索引。


猜你喜欢

转载自blog.csdn.net/caisongcheng_good/article/details/80698789