【发布时间】:2012-02-14 22:29:21
【问题描述】:
索引在 SQL 中是如何工作的,它有什么好处?没有索引的原因是什么?索引单列与索引多列有什么区别?
【问题讨论】:
索引在 SQL 中是如何工作的,它有什么好处?没有索引的原因是什么?索引单列与索引多列有什么区别?
【问题讨论】:
索引在 SQL 中是如何工作的,它有什么好处?
当您为列编制索引时,您表达了在条件表达式中查询索引列的意图,例如相等或范围查询。有了这些信息,存储引擎可以构建一个结构,使此类查询更快,通常将它们安排在树结构中。 B 树是最常见的,但存在许多不同的结构,例如散列索引、空间数据的 R 树索引等。每个结构都专门用于某种类型的查找。例如,哈希索引对于相等条件非常快,例如:
SELECT * FROM example_table WHERE type = "example";
SELECT * FROM example_table WHERE id = X;
B-trees 对于相等查找也相当快,但它们的主要优势在于它们支持范围查询:
SELECT * FROM example_table WHERE id > 5 AND id < 10
SELECT * FROM example_table WHERE type = "example" and value > 25
然而,当您构建 B-tree 索引以了解该树以“从左到右”的方式排序时,这一点非常重要。即,如果您在 {type, value} 上构建 B-tree 索引(我们称之为 A),那么您需要在 type-column 上有一个条件,以便查询能够利用该索引。示例索引不能用于条件仅取决于值的查询。 此外,如果您混合相等和范围条件,请确保相等列在索引中首先列出,否则只能部分使用索引。
没有索引的原因是什么?
如果索引的选择性很低,那么您可能不会比表扫描获得太多收益。例如,假设您在名为性别的字段上有一个索引。那么该索引的选择性就会很低,因为对该索引的查找将返回原始表的一半行。你可以在这里阅读关于选择性的非常简单的解释,以及其背后的原因:http://mattfleming.com/node/192
此外,维护索引是有成本的。对于每个数据操作,索引可能需要重组。因此,可能需要将索引数量保持在针对该表执行良好查询所需的最低限度。
索引单列与索引多列有什么区别?
再一次,这取决于您发出的查询类型。索引单个列的性别可能不是一个好主意,因为选择性很低。 When the selectivity is high then such an index makes much more sense.例如,主键上的索引是一个非常好的索引,因为选择性很高(实际上,它是尽可能高的。索引中的每个键都与记录上的精确对应),以及具有唯一性或高度的列上的索引不同的值(例如 slug、密码哈希等等)也是很好的单列索引。
还有覆盖索引的概念。基本上,索引中的每个叶子都包含一个指向存储行的表的指针(除非索引是聚集索引。在这种情况下,叶子就是记录)。因此,对于每个索引命中,查询引擎都必须获取相应的表行,从而增加 I/O 操作的数量。由于 I/O 非常慢,因此您希望将其保持在最低限度。现在,假设您经常需要查询某些内容,并且还需要获取一些额外的列,那么您可以创建覆盖索引,用存储空间换取查询性能。示例:让我们查找过去 6 个月内加入的所有用户的姓名和电子邮件(假设 MySQL):
在 {joined_at} 上有索引:
SELECT first_name, last_name, email
FROM users
WHERE joined_at > NOW() - INTERVAL 6 MONTH;
查询说明:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users ALL test NULL NULL NULL 873 Using where
正如您在type 列中看到的那样,查询引擎采用了全表扫描,因为索引选择性太低,不值得在此查询中使用(返回的结果太多,因此遵循到表中,I/O 开销太大)
在 {joined_at, first_name, last_name, email} 上有索引:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users range test,test2 test2 8 NULL 514 Using where;
Using index
现在,由于完成查询所需的所有信息都在索引中可用,因此查询引擎评估认为使用索引(有 514 行)比进行全表扫描要好得多。 如您所见,通过使用覆盖索引,我们可以加快对表的部分选择的查询,即使索引的选择性非常小。
【讨论】:
索引在 SQL 中是如何工作的
这是一个非常开放的问题,但基本上数据库存储的结构可以更快地查找信息。该结构取决于实现,但它通常是一种树。
它有什么好处?
SARGable 查询可以明显更快。*
没有索引的原因是什么?
某些数据修改查询可能需要更长的时间,并且索引存在存储成本,但一般来说,这两个考虑因素都可以忽略不计。
索引单列与索引多列有什么区别?
没有太大区别,但有时人们会创建覆盖索引** 来索引多个列以提高特定查询的性能。
*SARGable 来自搜索 ARGument ABLE。基本上,如果你这样做WHERE FOO > 5,如果 FOO 被索引,它会更快。另一方面,WHERE h(FOO) > 5 可能不会从索引中受益。
** 如果语句的 SELECT JOIN 和 WHERE 中使用的所有字段也在索引中,则数据库可以检索所需的所有信息,而无需返回基表。这称为覆盖指数。如果所有字段都在单独的索引中,它只会将这些字段用于连接和位置,然后返回到选择中列的基表。
【讨论】: