MySQL索引是如何工作的?

MySQL索引是如何工作的?,mysql,indexing,Mysql,Indexing,我真正感兴趣的是MySQL索引是如何工作的,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据 我知道这是离题的,但如果有人能向我详细解释这一点,我将非常非常感谢。看看这个链接: 他们是如何工作的,这是一个太宽泛的主题,无法在一篇如此之多的文章中涵盖 这是我见过的对指数最好的解释之一。不幸的是,它是针对SQL Server的,而不是针对MySQL的。我不确定两者有多相似…基本上,索引是按顺序排序的所有键的映射。按顺序排列一个列表,然后它可以执行如下操作,而不是检查每个键: SELECT u

我真正感兴趣的是MySQL索引是如何工作的,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据


我知道这是离题的,但如果有人能向我详细解释这一点,我将非常非常感谢。

看看这个链接:

他们是如何工作的,这是一个太宽泛的主题,无法在一篇如此之多的文章中涵盖


这是我见过的对指数最好的解释之一。不幸的是,它是针对SQL Server的,而不是针对MySQL的。我不确定两者有多相似…

基本上,索引是按顺序排序的所有键的映射。按顺序排列一个列表,然后它可以执行如下操作,而不是检查每个键:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
1:转到列表的中间-比我要找的要高还是要低

2:如果较高,则转到中间和底部之间的中间点,如果较低,则转到中间和顶部之间的中间点

3:是高还是低?再次跳到中间点等

使用这种逻辑,您可以通过大约7个步骤在排序列表中找到一个元素,而不是检查每个项目


显然有很多复杂之处,但这给了你一个基本的想法。

基本上,表上的索引就像书中的索引一样工作(这就是名称的来源):

假设你有一本关于数据库的书,你想找到一些关于存储的信息。如果没有索引(假设没有其他帮助,例如目录),您必须逐个浏览页面,直到找到主题(这是
全表扫描
)。 另一方面,索引有一个关键字列表,因此您可以查阅索引,并在第113-120231页和第354页中提到
存储
。然后,您可以直接翻到这些页面,而无需搜索(这是一个带有索引的搜索,速度更快)

当然,索引的有用程度取决于许多事情——使用上面的比喻,举几个例子:

  • 如果你有一本关于数据库的书,并为“数据库”这个词编制了索引,你会看到第1-59页、第61-290页和第292-400页都提到了它。在这种情况下,索引没有多大帮助,逐个浏览页面可能会更快(在数据库中,这是“选择性差”)
  • 对于一本10页的书来说,建立索引是没有意义的,因为你可能会得到一本10页的书,前面加了一个5页索引,这太傻了——只需扫描10页就可以了
  • 索引也需要有用-通常没有索引的意义,例如每页字母“L”的频率

您必须知道的第一件事是,索引是一种避免扫描整个表以获得所需结果的方法

有不同类型的索引,它们是在存储层实现的,因此它们之间没有标准,它们还取决于您使用的存储引擎

InnoDB和B+树索引 对于InnoDB,最常见的索引类型是基于B+树的索引,它按排序顺序存储元素。此外,您不必访问实际表来获取索引值,这使得查询返回速度更快

这种索引类型的“问题”是,必须查询最左边的值才能使用索引。因此,如果索引有两列,比如姓和名,那么查询这些字段的顺序非常重要

因此,根据下表:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);
此查询将利用索引:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
但接下来的一个不会

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
因为您首先查询的是
first\u name
列,而它不是索引中最左边的列

最后一个例子更糟糕:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
因为现在,您正在比较索引中最右边字段的最右边部分

散列索引 不幸的是,这是一种只有内存后端支持的不同索引类型。它的速度非常快,但只对完全查找有用,这意味着您不能将其用于诸如
之类的操作。有关索引的详细信息,请观看视频

简单索引 可以在表上创建唯一索引。唯一索引意味着两行不能具有相同的索引值。下面是在表上创建索引的语法

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);
可以使用一个或多个列创建索引。例如,我们可以使用tutorial\u author在
tutorials\u tbl
上创建索引

CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)
可以在表上创建简单索引。只需从查询中省略UNIQUE关键字即可创建简单索引。简单索引允许表中存在重复值

如果要按降序为列中的值编制索引,可以在列名后添加保留字DESC

mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)

我想加上我的2美分。我远不是一个数据库专家,但我最近读了一些关于这个主题的书;足够我试着给一个ELI5。所以,下面是梅·门外汉的解释


我的理解是,索引就像是表的一个小镜像,非常像一个关联数组。如果你给它一个匹配的键,那么你可以在一个“命令”中跳转到那一行

但是如果没有索引/数组,查询解释器必须使用for循环遍历所有行并检查匹配(完整表扫描)

拥有索引有额外存储的“缺点”(对于迷你镜像而言),以换取更快查找内容的“优点”


请注意(取决于您的db引擎),创建主键、外键或唯一键也会自动设置相应的索引。基本上,相同的原理就是这些键工作的原因和方式。

在答案列表中添加一些视觉表示

MySQL使用了额外的间接层:辅助索引记录指向主索引记录,主索引本身保存磁盘上的行位置。如果行偏移量发生更改,则只需更新主索引

警告:磁盘数据结构在图中看起来是扁平的,但实际上是一个 B+树

资料来源:<
mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)