【问题标题】:How do MySQL indexes work?MySQL 索引是如何工作的?
【发布时间】:2011-04-03 20:05:11
【问题描述】:

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

这是题外话,我知道,但如果有人可以向我详细解释,我将非常非常感谢。

【问题讨论】:

  • 这是一个非常广泛的问题。如果您有一个不使用索引的特定查询示例,并且您不知道原因,您可以发布它,人们可能会提供帮助。
  • SELECT * FROM members WHERE id = '1' - 那么为什么使用索引它可以更快地工作?该索引在这里做什么?
  • 这看起来像一个查询,它只查找特定的索引记录(可能由主键标识)。索引使这更快,因为它存储在内存中,可以查看相应的索引行,并且它包含指向实际数据存储位置的指针。所以 MySQL 可以直接到表中的确切位置,而无需扫描表。
  • 很好,谢谢!

标签: mysql indexing


【解决方案1】:

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

假设您有一本关于数据库的书,并且您想查找一些关于存储的信息。如果没有索引(假设没有其他帮助,例如目录),您将不得不逐页浏览,直到找到主题(即full table scan)。 另一方面,索引有一个关键字列表,因此您可以查阅索引并看到在第 113-120,231 和 354 页上提到了storage。然后您可以直接翻到这些页面,而无需搜索(这是使用索引搜索,速度更快)。

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

  • 如果您有一本关于数据库的书并将“数据库”一词编入索引,您会看到它在第 1-59,61-290 页和第 292 至 400 页中被提及。在这种情况下,索引没有多大帮助并且逐页浏览可能会更快(在数据库中,这是“选择性差”)。
  • 对于一本 10 页的书,建立索引是没有意义的,因为您最终可能会得到一本 10 页的书,并以 5 页的索引为前缀,这很愚蠢 - 只需扫描 10 页并被完成了。
  • 索引也需要有用 - 通常没有索引的意义,例如每页字母“L”的频率。

【讨论】:

  • 您是在解释它是什么,而不是在技术上如何在内部工作。
  • @Tutu Kumari:查看问题的修改;随时修改答案以适合当前问题(注意各种引擎和索引类型 - 参见例如此处的文档:dev.mysql.com/doc/refman/8.0/en/index-btree-hash.html
  • 您能否提供一些“范围”,例如制作一个考虑“用户”表和“帖子”表的博客示例,您可以在其中进行组合搜索。在(大致)哪个数量级,或者在“有多少用户”和/或“多少个帖子”时,如果不是必须的话,是否会建议设置适当的索引?谢谢你是否有可能给一个想法或一些想法。谢谢您是否可以尝试给出从哪里开始担心索引(多少行/列)的阈值
【解决方案2】:

您必须知道的第一件事是索引是一种避免扫描整个表以获得您正在寻找的结果的方法。

索引有很多种,它们是在存储层实现的,因此它们之间没有标准,它们也取决于您使用的存储引擎。

InnoDB 和 B+Tree 索引

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

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

所以,给定下表:

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_name 列,并且它不是索引中最左边的列。

最后一个例子更糟糕:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

因为现在,您正在比较索引中最右侧字段的最右侧部分。

哈希索引

不幸的是,这是一种不同的索引类型,只有内存后端支持。它快如闪电,但仅对完整查找有用,这意味着您不能将其用于><LIKE 等操作。

由于它仅适用于内存后端,您可能不会经常使用它。我现在能想到的主要情况是,您在内存中创建一个临时表,其中包含来自另一个选择的一组结果,并使用哈希索引在这个临时表中执行许多其他选择。

如果您有一个大的VARCHAR 字段,您可以在使用 B-Tree 时“模拟”哈希索引的使用,方法是创建另一列并在其上保存大值的哈希。假设您将 url 存储在一个字段中,并且值非常大。您还可以创建一个名为 url_hash 的整数字段,并在插入 URL 时使用 CRC32 之类的哈希函数或任何其他哈希函数对 URL 进行哈希处理。然后,当您需要查询此值时,您可以执行以下操作:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

上述示例的问题在于,由于CRC32 函数生成的散列非常小,因此您最终会在散列值中遇到很多冲突。如果您需要准确的值,您可以通过执行以下操作来解决此问题:

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

即使冲突数很高,仍然值得对事物进行哈希处理,因为您只会针对重复的哈希执行第二次比较(字符串一)。

不幸的是,使用这种技术,你仍然需要打表来比较url字段。

总结

您每次谈论优化时可能会考虑的一些事实:

  1. 整数比较比字符串比较快。可以用InnoDB中的hash索引模拟的例子来说明。

  2. 也许,在流程中添加额外的步骤会使其更快,而不是更慢。这可以通过以下事实来说明:您可以通过将SELECT 拆分为两个步骤来优化它,使第一个将值存储在新创建的内存表中,然后在第二个表上执行更重的查询。

MySQL 也有其他索引,但我认为 B+Tree 索引是最常用的,而哈希索引是一件好事,但您可以在 MySQL documentation 中找到其他索引。

我强烈推荐你阅读“高性能 MySQL”这本书,上面的答案肯定是基于它关于索引的章节。

【讨论】:

  • 以下查询在上述情况下是否有优势?1.SELECT last_name, first_name FROM person WHERE last_name= "Constantine" 2.SELECT last_name, first_name FROM person WHERE last_name LIKE "%Constantine"
  • 第一次查询会,第二次不会。使用 EXPLAIN:dev.mysql.com/doc/refman/5.5/en/explain.html 要使用 MySQL 索引第二个查询,您必须使用 FULLTEXT INDEX:dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
  • 我投票赞成你,因为你的排名是 127,而排名第一的答案是 256。我无法避免让一切都变得干净整洁,二进制。
  • 这对我来说是新信息“查询这些字段的顺序很重要。”谢谢。
  • @pbarney 三年后他们分别接近 256 和 512,这就是我所说的二进制增长!
【解决方案3】:

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

1:转到列表中间 - 比我要找的要高还是低?

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

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

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

显然存在复杂性,但这为您提供了基本概念。

【讨论】:

  • 这称为二分查找。
  • 谢谢,终于有一个答案解释了为什么它更快,而不仅仅是数据库如何使用索引。
  • 实际的步数很大程度上取决于数据——唯一值的数量和在您的范围内的分布。 7 是 100 个值的理论最大值。此处全面讨论如何计算步数stackoverflow.com/questions/10571170/…
  • 最常见的 MySQL 索引是 B+Tree,其工作方式类似于二分搜索,但不完全相同。算法复杂度相同,但搜索方式不同。见en.wikipedia.org/wiki/B-tree
【解决方案4】:

看看这个链接:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

它们的工作原理过于宽泛,无法在一篇 SO 帖子中涵盖。

Here 是我见过的对索引最好的解释之一。不幸的是,它适用于 SQL Server 而不是 MySQL。我不确定这两者有多相似......

【讨论】:

  • 好文章。我不了解 SQL Server,但基本工作原理看起来非常相似。 (元注:在第二篇链接文章中禁用 CSS 样式会取消隐藏内容)
【解决方案5】:

观看this 视频以了解有关索引的更多详细信息

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

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);

您可以使用一列或多列来创建索引。例如,我们可以使用 tutorial_author 在tutorials_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)

【讨论】:

【解决方案6】:

在 MySQL InnoDB 中,有两种类型的索引。

  1. 主键,称为聚集索引。索引关键字存储在 B+Tree叶子节点中的真实记录数据。

  2. 辅助键是非聚集索引。这些索引只将主键的关键词与它们自己的索引关键词一起存储在 B+Tree 叶节点中。所以从二级索引搜索时,会先找到它的主键索引关键词,然后扫描主键B+Tree,找到真正的数据记录。与主索引搜索相比,这将使二级索引变慢。但是,如果select列都在二级索引中,则无需再次查找主索引B+Tree。这称为覆盖索引。

【讨论】:

    【解决方案7】:

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

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

    警告:磁盘数据结构在图中看起来很平坦,但实际上是 B+ 树。

    来源:link

    【讨论】:

      【解决方案8】:

      我想加我的 2 美分。我远不是数据库专家,但我最近阅读了一些关于这个主题的文章;足以让我尝试并给出 ELI5。所以,这里可能是外行的解释。


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

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

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

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

      【讨论】:

        【解决方案9】:

        假设你有一本书,可能是一本小说,一本厚厚的书,有很多东西要读,因此有很多词。 现在,假设您带来了两本字典,只包含小说中至少一次使用过的单词。 两个字典中的所有单词都按典型的字母顺序存储。在假设字典 A 中,单词只打印一次,而在 假设字典 B 中,单词被打印与打印次数一样多在小说中。请记住,两个词典中的单词都是按字母顺序排序的。 现在,您在阅读小说时遇到了某个问题,需要从这些假设字典中的任何一个中找到该词的含义。你会做什么?你肯定会在几个步骤中跳到那个词来找到它的意思,而不是寻找小说中每个词的意思,从头开始,直到你找到那个令人讨厌的词。

        这就是索引在 SQL 中的工作方式。将字典 A 视为 PRIMARY INDEX,将字典 B 视为 KEY/SECONDARY INDEX,并且您希望将单词的含义视为 QUERY/SELECT STATEMENT。 该索引将有助于以非常快的速度获取数据。如果没有索引,您将不得不从一开始就查找数据,这是不必要的耗时昂贵的任务。

        有关索引和类型的更多信息,look this

        【讨论】:

          猜你喜欢
          • 2012-04-24
          • 1970-01-01
          • 2022-01-02
          • 1970-01-01
          • 2018-11-27
          • 1970-01-01
          • 1970-01-01
          • 2010-10-22
          相关资源
          最近更新 更多