我对MySQL索引的工作方式非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据?
我知道这是题外话,但是如果有人可以向我详细解释一下,我将非常非常感谢。
SELECT * FROM members WHERE id = '1'
-那么为什么使用索引可以更快?该索引在这里做什么?
我对MySQL索引的工作方式非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据?
我知道这是题外话,但是如果有人可以向我详细解释一下,我将非常非常感谢。
SELECT * FROM members WHERE id = '1'
-那么为什么使用索引可以更快?该索引在这里做什么?
Answers:
基本上,表上的索引的作用类似于书中的索引(这就是名称的来源):
假设您有一本关于数据库的书,并且想要查找有关存储的信息。没有索引(假设没有其他帮助,例如目录),则必须逐个浏览页面,直到找到主题(即full table scan
)为止。另一方面,索引包含关键字列表,因此您可以查阅该索引,并storage
在第113-120,231和354页中看到该索引。然后,您可以直接翻到这些页面,而无需进行搜索(即使用索引,速度更快)。
当然,索引的有用程度取决于很多事情-使用上面的比喻的几个例子:
您必须知道的第一件事就是索引是一种避免扫描整个表以获得所需结果的方法。
索引有不同种类,它们在存储层中实现,因此它们之间没有标准,它们还取决于您使用的存储引擎。
对于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树时哈希索引的使用。假设您将url存储在字段中,并且值很大。您还可以创建一个名为的整数字段,url_hash
并CRC32
在插入URL时使用像之类的哈希函数或任何其他哈希函数对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
字段。
您每次谈论优化时都可能要考虑的一些事实:
整数比较比字符串比较要快得多。可以用有关在中模拟哈希索引的示例进行说明InnoDB
。
也许,在过程中添加其他步骤可以使其更快而不是更慢。您可以SELECT
通过将a 分为两个步骤来优化它,将第一个步骤存储在新创建的内存表中,然后在第二个表上执行较重的查询,来说明这一点。
MySQL也有其他索引,但是我认为B + Tree索引是有史以来使用最多的索引,而哈希索引是个好消息,但是您可以在MySQL文档中找到其他索引。
我强烈建议您阅读“高性能MySQL”这本书,上面的答案肯定基于其有关索引的章节。
SELECT last_name, first_name FROM person WHERE last_name= "Constantine"
2.SELECT last_name, first_name FROM person WHERE last_name LIKE "%Constantine"
基本上,索引是按顺序排列的所有键的映射。按顺序排列列表,然后无需检查每个键,而是可以执行以下操作:
1:转到列表的中间-高于或低于我要查找的内容?
2:如果较高,则到达中间和底部之间的中点;如果较低,则到达中间和顶部之间的中点
3:是更高还是更低?再次跳到中间点,依此类推。
使用该逻辑,您可以在大约7个步骤中在排序列表中找到一个元素,而不用检查每个项目。
显然存在复杂性,但这给了您基本的思想。
看一下这个链接:http : //dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
它们的工作方式太广泛,无法在一个SO职位中讨论。
这是我所见过的索引的最佳解释之一。不幸的是,它是针对SQL Server而不是MySQL。我不确定两者的相似程度...
快来看看这个视频有关索引更多详情
简单索引您可以在表上创建唯一索引。唯一索引意味着两行不能具有相同的索引值。这是在表上创建索引的语法
CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);
您可以使用一个或多个列来创建索引。例如,我们可以tutorials_tbl
使用tutorial_author 创建索引。
CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)
您可以在表上创建一个简单的索引。只需从查询中省略UNIQUE关键字即可创建简单索引。简单索引允许表中有重复值。
如果要按降序索引列中的值,可以在列名后添加保留字DESC。
mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)
在MySQL InnoDB中,有两种类型的索引。
主键,称为聚簇索引。索引关键字与实际记录数据一起存储在B + Tree叶子节点中。
次键是非聚集索引。这些索引仅将主键的关键字以及它们自己的索引关键字存储在B + Tree叶子节点中。因此,从二级索引搜索时,它将首先找到其主键索引关键字,然后扫描主键B + Tree来查找真实的数据记录。与主索引搜索相比,这将使二级索引变慢。但是,如果select
列都在辅助索引中,则无需再次查找主索引B + Tree。这称为覆盖指数。