Mysql 索引的基础(上)

  要理解Mysql 中索引是如何工作的,最简单的方法是去看一看书的"索引部分":如果想在一本书中找到某个特定的主题,一般先看书的"索引",找到对应的页码。

  在Mysql中,存储引擎用类似的方法使用索引,其先在索引中找到对应的值,然后根据匹配的索记录找到对应的数据行。加入要运行下面的查询:

select first_name FROM user where user_id = 5;

如果在user_id上建有索引,则mysql将使用该索引找到user_id=5的行,也就是说,mysql 先在索引上按值查找,然后返回所有包含该值的数据行。

  索引可以包含一个或多个的值。如果索引包含多个列,那么列的顺序也十分重要,因为mysql 只能高效的使用索引的最左前缀列。创建一个包含两个列的索引,和创建两个只包含一个列的索引是大不相同的,下面将详细介绍。

  索引的类型

  索引有很多种类型,可以为不同的场景提供更好的性能.在Mysql中,索引是在存储引擎层实现的而不是服务器层实现的。所以没有同意的索引标准:不同的存储引擎的索引的工作方式不一样,也不是所有的存储引擎都支持所有类型的索引。即使多个存储引擎支持同一种类型的索引,其底层实现也可能不同。

  下面我们来看看mysql支持的索引类型,以及他们的优缺点。

  B-Tree 索引

  当人们讨论索引的时候,如果没有特别指明类型,那么多半说的是B-Tree索引,它使用B-Tree数据结构来存储数据。大多数MySQL引擎都支持这种索引。

  我们使用术语“B-Tree” ,因为MySQL 在create table 和其他语句中也使用该关键字。不过,底层的存储引擎也坑能使用不同的存储结构,例如,NDB集群存储引擎内部实际上使用了T-Tree 结构存储这种索引,即使其名字是Btree;innodb则使用的是B+Tree。

  存储引擎以不同的方式使用了B-Tree索引,性能也各有不同,各有优势,例如,MyISAM 使用前缀压缩技术使得索引更小,蛋InnoDB 则按照原数据格式进行存储。在如MyIsam索引通过数据的物理位置引用被索引的行,而InnoDB索引则根据住建引用被索引的行。

  B-Tree 通常意味着所有的值都是按照顺序存储的,而且每一个叶子页到根的距离相同。

  B-Tree 索引能够加快访问数据的速度,因为存储引擎不在需要进行全表扫描来获取需要的数据,取而代之的是从索引的根节点开始进行搜索。根节点值中存放了指向叶子节点的指针,存储引擎根据这些指针向下层查找。通过比较节点页的值和要操作的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点也中的值的上限和下限。最终存储引擎要么找到对应的值,要么该记录不存在。

  叶子节点比较特别,他们的指针指向的是被索引的数据,而不是其他的叶节点页(不同引擎的指针类型不同)。根的深度和表的大小直接相关。

  B-Tree 对索引列是顺序组织存储的,所以很适合查找范围数据。例如,在一个机遇文本域的索引树上,按字母书序传递连续的值进行查找是非常合适的,所以像“找出所有以I到K开头的名字”这样的查找效率会非常高。

  请注意,索引对多个值进行排序的一句是CREATE TABLE 语句中定义的所以时的列的顺序。

  可以使用B-Tree索引的查询类型。B-Tree 索引适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。前面所述的索引对如下类型的查询有效:

  全值匹配

  全值匹配指的是和索引中所有的列进行匹配。

  匹配最左前缀

  前面提到的索引可以用于查找出所有姓为Allen的人,即只使用索引的第一列。

  匹配列前缀

  也可以值匹配莫一列的值开头部分。

  匹配范围值

  精确匹配某一列并范围匹配另一列

  只访问索引的查询

  

  因为索引树种的节点是有顺序的,所以除了按值查找之外,索引还可以用于查询中的ORDER BY操作。一般来说,如果B-Tree 可以按照某种方式查找到值,那么也可以按照这种方式用于排序,所以,如果ORDER BY 子句满足前面列出的集中查询类型,则这个索引也可以满足对应的排序需求。

  下面是一些关于B-Tree索引的限制:

  如果不是按照索引的最左列开始查找,则无法使用索引。例如,上面的列子中的索引无法用于超找名字为Bill的人,也无法查找某个特定生日的人,因为这两列都不是最左数据列。类似的,也无法超找姓氏以某个字母结尾的人。

  不能跳过索引中的列。也就是说,前面所述的索引无法用于查找姓为Smith并且在特定日期出生的人。如果不指定名(first_name),则MySQL只能用于索引的第一列。

  如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引优化查找。例如查询WHERE last_name ='Smith' AND first_name LIKE "J%" AND dob = '1990-10-10',这个查询只能使用索引的前两列,因为这里LIKE是一个范围条件。如果范围查询列值的数量有限,那么可以通过使用多个等于条件来替代范围条件。

  到这里读者应该可以明白,前面提到的索引列的顺序是多么重要:这些限制都和索引的顺序有关。在优化性能的时候,可能需要使用相同的列的顺序不同的索引来满足不同类型的查询需求。

  也有些限制并不是B-Tree本身导致的,而是MySQL优化器和存储引擎使用索引的方式导致的,这部分限制在未来的版本中可能就不再限制了。

  

原文地址:https://www.cnblogs.com/zhengyanqiu/p/4976262.html