我非常感兴趣的是mysql索引是如何工作的,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据?这是离题的,我知道,但如果有人能向我详细解释这一点,我将非常非常感谢。
v8wbuo2f1#
在答案列表中添加一些视觉表现。mysql使用了一个额外的间接层:辅助索引记录指向主索引记录,而主索引本身保存磁盘上的行位置。如果行偏移量更改,则只需要更新主索引。警告:磁盘数据结构在图中看起来是扁平的,但实际上是一个b+树。来源:链接
o2g1uqev2#
有关索引的更多详细信息,请观看此视频简单索引您可以在表上创建唯一索引。唯一索引意味着两行不能具有相同的索引值。下面是在表上创建索引的语法
CREATE UNIQUE INDEX index_name ON table_name ( column1, column2,...);
可以使用一列或多列创建索引。例如,我们可以在 tutorials_tbl 使用教程作者。
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)
5kgi1eie3#
看看这个链接:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html他们是如何工作的,这个主题太宽泛了,不可能在一篇这样的文章中涵盖。以下是我见过的关于指数的最好解释之一。不幸的是,它是针对sql server的,而不是针对mysql的。我不知道两者有多相似。。。
k2arahey4#
假设你有一本书,可能是一本小说,一本厚厚的书,里面有很多东西要读,因此有很多单词。现在,假设你带了两本字典,只包含了小说中至少一次只使用过的单词。这两本词典中的所有单词都按典型的字母顺序存储。在假想词典a中,单词只打印一次,而在假想词典b中,单词打印的次数与小说中打印的次数相同。记住,单词在两本词典中都是按字母顺序排列的。现在你在读小说的时候遇到了困难,需要从任何一本假想词典中找出这个词的意思。你会怎么做?当然,你会跳到这个词的几个步骤,找到它的意思,而不是寻找每一个词的意思,在小说中,从一开始,直到你达到那个讨厌的词。这就是索引在sql中的工作方式。将dictionary a作为主索引,dictionary b作为键/辅助索引,并将您想要获取单词含义的愿望作为查询/选择语句。索引将有助于以非常快的速度获取数据。如果没有索引,您将不得不从一开始就查找数据,这是一项不必要的费时费力的任务。对于
8nuwlpux5#
我想加上我的2美分。我远不是一个数据库Maven,但我最近读了一些关于这个主题的文章;足以让我试着给一个eli5。所以,这是梅外行的解释。我的理解是,索引就像表的小镜子,非常像关联数组。如果你给它一个匹配的键,那么你只需在一个“命令”中跳到那一行。但是如果没有索引/数组,查询解释器必须使用for循环遍历所有行并检查匹配(完整表扫描)。拥有一个索引有额外存储的“缺点”(对于那个小镜子),而交换的“好处”是更快地查找内容。请注意,创建主键、外键或唯一键(取决于数据库引擎)也会自动设置相应的索引。同样的原理基本上就是这些键工作的原因和方式。
nfzehxib6#
您必须知道的第一件事是,索引是一种避免扫描整个表以获得所需结果的方法。索引有不同的种类,它们是在存储层实现的,因此它们之间没有标准,而且它们还取决于您使用的存储引擎。
对于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_name 列,它不是索引中最左边的列。最后一个例子更糟:
first_name
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
因为现在,您正在比较索引中最右边字段的最右边部分。
不幸的是,这是另一种索引类型,只有内存后端支持。它的速度非常快,但只对完全查找有用,这意味着您不能将它用于像这样的操作 > , < 或者 LIKE .因为它只适用于内存后端,所以您可能不会经常使用它。我现在能想到的主要情况是,在内存中创建一个临时表,其中包含一组来自另一个select的结果,并使用哈希索引在这个临时表中执行许多其他select。如果你有一个大的 VARCHAR 字段中,您可以“模拟”使用b树时使用哈希索引,方法是创建另一列并在其上保存一个大值的哈希。假设您在一个字段中存储一个url,并且值非常大。您还可以创建一个名为 url_hash 使用哈希函数,比如 CRC32 或任何其他哈希函数,以在插入url时对其进行哈希。然后,当您需要查询此值时,可以执行以下操作:
>
<
LIKE
VARCHAR
url_hash
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 现场。
url
每次谈论优化时,您可能会考虑一些事实:整数比较比字符串比较快得多。可以用中哈希索引仿真的例子来说明 InnoDB .也许,在一个过程中添加额外的步骤会使它更快,而不是更慢。这可以通过您可以优化 SELECT 通过将其分为两个步骤,使第一个步骤将值存储在新创建的内存表中,然后对第二个表执行更重的查询。mysql也有其他索引,但我认为b+树索引是有史以来使用最多的索引,hash索引是一件很好的事情,但是你可以在mysql文档中找到其他索引。我强烈建议您阅读“高性能mysql”一书,上面的答案肯定是基于它关于索引的章节。
InnoDB
SELECT
juud5qan7#
基本上,表上的索引就像书中的索引一样工作(这就是名称的来源):假设你有一本关于数据库的书,你想找到一些关于存储的信息。如果没有索引(假设没有其他辅助工具,比如目录),你就必须一个接一个地浏览页面,直到找到主题(这是一个 full table scan ). 另一方面,索引有一个关键字列表,所以您可以查阅索引并查看它 storage 第113-120231页和第354页提到。然后你可以直接翻到那些页面,而不需要搜索(这是一个带有索引的搜索,稍微快一点)。当然,索引的有用程度取决于许多因素——例如,使用上面的比喻:如果你有一本关于数据库的书,并且索引了“数据库”这个词,你会看到它在第1-59页、第61-290页和第292-400页被提到。在这种情况下,索引没有多大帮助,一页一页地浏览页面可能会更快(在数据库中,这是“选择性差”)。对于一本10页的书来说,建立索引是没有意义的,因为你可能会以一本10页的书加上一个5页的索引作为结尾,这太傻了——只要扫描10页就可以了。索引也需要是有用的-通常没有索引点,例如每页字母“l”的频率。
full table scan
storage
e7arh2l68#
基本上,索引是按顺序排列的所有键的Map。通过按顺序排列的列表,它可以执行以下操作,而不是检查每个键:1:到列表中间-比我要找的东西高还是低?2:如果较高,则转到中间和底部之间的中点,如果较低,则转到中间和顶部3:高还是低?再跳到中间点等。使用这种逻辑,您可以在大约7个步骤中找到排序列表中的元素,而不是检查每个项目。很明显有复杂性,但这给了你基本的想法。
fcwjkofz9#
在mysql innodb中,有两种类型的索引。主键,称为聚集索引。索引关键字与实际记录数据一起存储在b+树叶子节点中。非聚集索引的次键。这些索引只将主键的关键字与自己的索引关键字一起存储在b+树叶子节点中。因此,当从二级索引进行搜索时,它首先会找到它的主键索引关键字,然后扫描主键b+树来找到真正的数据记录。这将使辅助索引比主索引搜索速度慢。但是,如果 select 列都在二级索引中,则无需再次查找主索引b+树。这叫做覆盖指数。
select
9条答案
按热度按时间v8wbuo2f1#
在答案列表中添加一些视觉表现。
mysql使用了一个额外的间接层:辅助索引记录指向主索引记录,而主索引本身保存磁盘上的行位置。如果行偏移量更改,则只需要更新主索引。
警告:磁盘数据结构在图中看起来是扁平的,但实际上是一个b+树。
来源:链接
o2g1uqev2#
有关索引的更多详细信息,请观看此视频
简单索引您可以在表上创建唯一索引。唯一索引意味着两行不能具有相同的索引值。下面是在表上创建索引的语法
可以使用一列或多列创建索引。例如,我们可以在
tutorials_tbl
使用教程作者。可以在表上创建简单索引。只需从查询中省略unique关键字即可创建简单索引。简单索引允许表中有重复的值。
如果要按降序对列中的值进行索引,可以在列名后添加保留字desc。
5kgi1eie3#
看看这个链接:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
他们是如何工作的,这个主题太宽泛了,不可能在一篇这样的文章中涵盖。
以下是我见过的关于指数的最好解释之一。不幸的是,它是针对sql server的,而不是针对mysql的。我不知道两者有多相似。。。
k2arahey4#
假设你有一本书,可能是一本小说,一本厚厚的书,里面有很多东西要读,因此有很多单词。现在,假设你带了两本字典,只包含了小说中至少一次只使用过的单词。这两本词典中的所有单词都按典型的字母顺序存储。在假想词典a中,单词只打印一次,而在假想词典b中,单词打印的次数与小说中打印的次数相同。记住,单词在两本词典中都是按字母顺序排列的。现在你在读小说的时候遇到了困难,需要从任何一本假想词典中找出这个词的意思。你会怎么做?当然,你会跳到这个词的几个步骤,找到它的意思,而不是寻找每一个词的意思,在小说中,从一开始,直到你达到那个讨厌的词。
这就是索引在sql中的工作方式。将dictionary a作为主索引,dictionary b作为键/辅助索引,并将您想要获取单词含义的愿望作为查询/选择语句。索引将有助于以非常快的速度获取数据。如果没有索引,您将不得不从一开始就查找数据,这是一项不必要的费时费力的任务。
对于
8nuwlpux5#
我想加上我的2美分。我远不是一个数据库Maven,但我最近读了一些关于这个主题的文章;足以让我试着给一个eli5。所以,这是梅外行的解释。
我的理解是,索引就像表的小镜子,非常像关联数组。如果你给它一个匹配的键,那么你只需在一个“命令”中跳到那一行。
但是如果没有索引/数组,查询解释器必须使用for循环遍历所有行并检查匹配(完整表扫描)。
拥有一个索引有额外存储的“缺点”(对于那个小镜子),而交换的“好处”是更快地查找内容。
请注意,创建主键、外键或唯一键(取决于数据库引擎)也会自动设置相应的索引。同样的原理基本上就是这些键工作的原因和方式。
nfzehxib6#
您必须知道的第一件事是,索引是一种避免扫描整个表以获得所需结果的方法。
索引有不同的种类,它们是在存储层实现的,因此它们之间没有标准,而且它们还取决于您使用的存储引擎。
innodb和b+树索引
对于innodb,最常见的索引类型是基于b+树的索引,它按排序顺序存储元素。另外,您不必访问实表来获取索引值,这使得查询返回速度更快。
关于这个索引类型的“问题”是您必须查询最左边的值才能使用索引。因此,如果索引有两列,比如姓和名,那么查询这些字段的顺序非常重要。
因此,给出下表:
此查询将利用索引:
但接下来的一个不会
因为你在查询
first_name
列,它不是索引中最左边的列。最后一个例子更糟:
因为现在,您正在比较索引中最右边字段的最右边部分。
哈希索引
不幸的是,这是另一种索引类型,只有内存后端支持。它的速度非常快,但只对完全查找有用,这意味着您不能将它用于像这样的操作
>
,<
或者LIKE
.因为它只适用于内存后端,所以您可能不会经常使用它。我现在能想到的主要情况是,在内存中创建一个临时表,其中包含一组来自另一个select的结果,并使用哈希索引在这个临时表中执行许多其他select。
如果你有一个大的
VARCHAR
字段中,您可以“模拟”使用b树时使用哈希索引,方法是创建另一列并在其上保存一个大值的哈希。假设您在一个字段中存储一个url,并且值非常大。您还可以创建一个名为url_hash
使用哈希函数,比如CRC32
或任何其他哈希函数,以在插入url时对其进行哈希。然后,当您需要查询此值时,可以执行以下操作:上面这个例子的问题是
CRC32
函数生成一个非常小的散列,散列值中会有很多冲突。如果需要精确的值,可以通过执行以下操作解决此问题:即使冲突数很高,散列仍然是值得的,因为您只需要对重复的散列执行第二次比较(字符串比较)。
不幸的是,使用这种技术,您仍然需要点击表格来比较
url
现场。总结
每次谈论优化时,您可能会考虑一些事实:
整数比较比字符串比较快得多。可以用中哈希索引仿真的例子来说明
InnoDB
.也许,在一个过程中添加额外的步骤会使它更快,而不是更慢。这可以通过您可以优化
SELECT
通过将其分为两个步骤,使第一个步骤将值存储在新创建的内存表中,然后对第二个表执行更重的查询。mysql也有其他索引,但我认为b+树索引是有史以来使用最多的索引,hash索引是一件很好的事情,但是你可以在mysql文档中找到其他索引。
我强烈建议您阅读“高性能mysql”一书,上面的答案肯定是基于它关于索引的章节。
juud5qan7#
基本上,表上的索引就像书中的索引一样工作(这就是名称的来源):
假设你有一本关于数据库的书,你想找到一些关于存储的信息。如果没有索引(假设没有其他辅助工具,比如目录),你就必须一个接一个地浏览页面,直到找到主题(这是一个
full table scan
). 另一方面,索引有一个关键字列表,所以您可以查阅索引并查看它storage
第113-120231页和第354页提到。然后你可以直接翻到那些页面,而不需要搜索(这是一个带有索引的搜索,稍微快一点)。当然,索引的有用程度取决于许多因素——例如,使用上面的比喻:
如果你有一本关于数据库的书,并且索引了“数据库”这个词,你会看到它在第1-59页、第61-290页和第292-400页被提到。在这种情况下,索引没有多大帮助,一页一页地浏览页面可能会更快(在数据库中,这是“选择性差”)。
对于一本10页的书来说,建立索引是没有意义的,因为你可能会以一本10页的书加上一个5页的索引作为结尾,这太傻了——只要扫描10页就可以了。
索引也需要是有用的-通常没有索引点,例如每页字母“l”的频率。
e7arh2l68#
基本上,索引是按顺序排列的所有键的Map。通过按顺序排列的列表,它可以执行以下操作,而不是检查每个键:
1:到列表中间-比我要找的东西高还是低?
2:如果较高,则转到中间和底部之间的中点,如果较低,则转到中间和顶部
3:高还是低?再跳到中间点等。
使用这种逻辑,您可以在大约7个步骤中找到排序列表中的元素,而不是检查每个项目。
很明显有复杂性,但这给了你基本的想法。
fcwjkofz9#
在mysql innodb中,有两种类型的索引。
主键,称为聚集索引。索引关键字与实际记录数据一起存储在b+树叶子节点中。
非聚集索引的次键。这些索引只将主键的关键字与自己的索引关键字一起存储在b+树叶子节点中。因此,当从二级索引进行搜索时,它首先会找到它的主键索引关键字,然后扫描主键b+树来找到真正的数据记录。这将使辅助索引比主索引搜索速度慢。但是,如果
select
列都在二级索引中,则无需再次查找主索引b+树。这叫做覆盖指数。