【问题标题】:SQL Indexing: None, Single Column, and Multiple ColumnsSQL 索引:无、单列和多列
【发布时间】:2012-02-14 22:29:21
【问题描述】:

索引在 SQL 中是如何工作的,它有什么好处?没有索引的原因是什么?索引单列与索引多列有什么区别?

【问题讨论】:

    标签: sql indexing


    【解决方案1】:

    索引在 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 行)比进行全表扫描要好得多。 如您所见,通过使用覆盖索引,我们可以加快对表的部分选择的查询,即使索引的选择性非常小。

    【讨论】:

      【解决方案2】:

      索引在 SQL 中是如何工作的

      这是一个非常开放的问题,但基本上数据库存储的结构可以更快地查找信息。该结构取决于实现,但它通常是一种树。

      它有什么好处?

      SARGable 查询可以明显更快。*

      没有索引的原因是什么?

      某些数据修改查询可能需要更长的时间,并且索引存在存储成本,但一般来说,这两个考虑因素都可以忽略不计。

      索引单列与索引多列有什么区别?

      没有太大区别,但有时人们会创建覆盖索引** 来索引多个列以提高特定查询的性能。


      *SARGable 来自搜索 ARGument ABLE。基本上,如果你这样做WHERE FOO &gt; 5,如果 FOO 被索引,它会更快。另一方面,WHERE h(FOO) &gt; 5 可能不会从索引中受益。

      ** 如果语句的 SELECT JOIN 和 WHERE 中使用的所有字段也在索引中,则数据库可以检索所需的所有信息,而无需返回基表。这称为覆盖指数。如果所有字段都在单独的索引中,它只会将这些字段用于连接和位置,然后返回到选择中列的基表。

      【讨论】:

      • 感谢您快速提供信息丰富的回答。你认为你可以为我详细说明其中的一些吗? SARGable 是什么意思?将多列索引为单个索引与将相同的几列的一个索引放在一起有什么区别?
      • 我已经更新了我的答案,包括扩展 SARGable 和覆盖索引的想法
      猜你喜欢
      • 1970-01-01
      • 2011-01-25
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      相关资源
      最近更新 更多