我对MySQL索引的工作原理非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回所请求的数据?
我知道这离题了,但如果有人能给我详细解释一下,我会非常非常感谢。
我对MySQL索引的工作原理非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回所请求的数据?
我知道这离题了,但如果有人能给我详细解释一下,我会非常非常感谢。
当前回答
索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后通读整个表以找到相关的行。桌子越大,花费就越多。如果表中存在相关列的索引,MySQL可以快速确定要在数据文件中间查找的位置,而不必查看所有数据。这比按顺序读取每一行快得多。
索引添加一个包含搜索条件列和指针的数据结构 对象所在行的内存磁盘地址 其他信息 对索引数据结构进行排序,优化查询效率 该查询查找索引中的特定行;索引指向将查找剩余信息的指针。 索引将查询必须搜索的行数从17减少到4。
其他回答
看看这个链接:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
它们是如何工作的,这是一个太宽泛的主题,无法在一篇SO帖子中涵盖。
下面是我所见过的关于索引的最好的解释之一。不幸的是,它是SQL Server而不是MySQL。我不确定这两者有多相似……
基本上,索引是所有按顺序排序的键的映射。有了一个按顺序排列的列表,它就不需要检查每个键,而是可以这样做:
1:去列表的中间-比我想要的高还是低?
2:如果高,就去中间和底部的中间点,如果低,就去中间和顶部的中间点
3:是高还是低?再次跳转到中间点,等等。
使用该逻辑,您可以在大约7步的时间内在排序列表中找到一个元素,而不是检查每一项。
显然,这里有很多复杂的东西,但这给了你基本的概念。
您必须知道的第一件事是,索引是一种避免扫描整个表以获得您正在寻找的结果的方法。
有不同种类的索引,它们是在存储层实现的,所以它们之间没有标准,它们也取决于你使用的存储引擎。
InnoDB和B+树索引
对于InnoDB,最常见的索引类型是基于B+树的索引,它以排序的顺序存储元素。此外,您不必访问实际表来获取索引值,这使得您的查询返回速度更快。
关于这种索引类型的“问题”是,您必须查询最左边的值才能使用索引。因此,如果您的索引有两个列,例如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这样的哈希函数或任何其他哈希函数来哈希。然后,当你需要查询这个值时,你可以这样做:
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字段。
总结
每当你想谈论优化时,你可能会考虑一些事实:
整数比较比字符串比较快得多。以InnoDB中哈希索引仿真为例进行了说明。 也许,在流程中添加额外的步骤会使其更快,而不是更慢。可以通过以下事实来说明这一点:优化SELECT可以分为两个步骤,第一个步骤将值存储在新创建的内存表中,然后在第二个表上执行较重的查询。
MySQL也有其他索引,但我认为B+树索引是最常用的,哈希索引是一个很好的东西,但你可以在MySQL文档中找到其他索引。
我强烈推荐你去读“高性能MySQL”这本书,上面的答案肯定是基于它关于索引的章节。
Let's suppose you have a book, probably a novel, a thick one with lots of things to read, hence lots of words. Now, hypothetically, you brought two dictionaries, consisting of only words that are only used, at least one time in the novel. All words in that two dictionaries are stored in typical alphabetical order. In hypothetical dictionary A, words are printed only once while in hypothetical dictionary B words are printed as many numbers of times it is printed in the novel. Remember, words are sorted alphabetically in both the dictionaries. Now you got stuck at some point while reading a novel and need to find the meaning of that word from anyone of those hypothetical dictionaries. What you will do? Surely you will jump to that word in a few steps to find its meaning, rather look for the meaning of each of the words in the novel, from starting, until you reach that bugging word.
这就是SQL中索引的工作方式。假设字典A是PRIMARY INDEX,字典B是KEY/SECONDARY INDEX,并将获取单词含义的愿望作为QUERY/SELECT语句。 索引将有助于以非常快的速度获取数据。如果没有索引,您将不得不从头开始查找数据,这是一项不必要的耗时且昂贵的任务。
有关索引和类型的更多信息,请看这个。
在答案列表中添加一些可视化表示。
MySQL使用了一个额外的间接层:次要索引记录指向主索引记录,主索引本身保存磁盘上的行位置。如果行偏移量发生变化,则只需要更新主索引。
注意:磁盘数据结构在图中看起来是平面的,但实际上是一个 B +树。
来源:链接