【问题标题】:What is a MySQL covering index?什么是 MySQL 覆盖索引?
【发布时间】:2019-08-22 09:37:00
【问题描述】:

我看到documentation描述覆盖索引:

覆盖索引
一个索引,包括查询检索到的所有列。

是否意味着覆盖索引是特定的索引?

我认为覆盖指数是一种现象。

如果我按照文档的描述,那么请看下面的sql语句:

create index idx_name_age on table(id, name)
select id, name from table where id = 1
select id, name, age from table where id = 1

idx_name_age 是第一个语句中的覆盖索引,第二个不是。

所以我认为:覆盖索引是一种现象,而不是一个索引。

【问题讨论】:

  • 我又修改了问题。我在您提到的问题中阅读了对 Johan 的回答,他对covering index 的回答与文档的定义不同。
  • 我不明白你在这种情况下所说的现象是什么意思。
  • 假设它是“INDEX 的属性相对于 到特定的SELECT。”

标签: mysql indexing query-performance covering-index


【解决方案1】:

假设“覆盖”是特定SELECT 的索引的“一个属性相对。

一些例子:

select id, name from table where id = 1

    INDEX(id, name)       -- covering; best index
    INDEX(id, name, age)  -- covering, but overkill
    INDEX(age, name, id)  -- covering, but inefficient (might not be used)

select id, name, age from table where id = 1

    INDEX(id, name, age) -- Having `id` first is optimal, but any order is "covering"

正如已经指出的,如果这是 InnoDB 并且表有 PRIMARY KEY(id),那么这些二级索引都不值得拥有。

SELECT a FROM tbl GROUP BY b ORDER BY c

    No index is very useful since the GROUP BY and ORDER BY are not the same.
    INDEX(a,b,c)   -- in any order, is "covering"
    INDEX(b,c,a)   -- "covering", and perhaps optimal.
    INDEX(b,c,a,d) -- "covering", but 'bigger'

以小事大事。在执行SELECT COUNT(*) FROM ... 时,InnoDB 将(通常)选择“最小”索引来进行计数。

另一个“规则”是避免冗余索引。

    INDEX(a,b)  -- Let's say you 'need' this one.
    INDEX(a)    -- Then this one is redundant and should be dropped.

【讨论】:

    【解决方案2】:

    覆盖索引是否为特定索引?

    是的,它是专门为满足特定查询而设计的索引。

    对于这个查询

    select id, name, age from table where id = 1
    

    覆盖索引是由(id, name, age)创建的多列索引

    create index idx_name_age on table(id, name, age)
    

    怎么样?

    id 是索引中的第一列,因为它在 WHERE id = 1 中使用。首先是因为 MySQL 索引通常是 BTREE,按索引顺序随机访问。所以WHERE id = 1 可以跳转,在索引中找到那些id 值。

    name 和 age 也出现在索引中,因为它们出现在 SELECT 子句中。因为它们在索引中,查询可以完全从索引中得到满足。这很好,因为它减少了从磁盘或 ssd 的读取:MySQL 不必使用索引来查找行在主表中才能满足查询。

    仅(id, name) 上的索引不是上述查询的覆盖索引;缺少age 列。

    这个查询

    select id, name from table where id = 1
    

    也可以通过 (id, name, age) 覆盖索引来满足。它也可以通过(id, name) 上的索引来满足:是第二个查询的覆盖索引(但不是第一个)。

    您的示例说明了词汇表的定义。索引通过使用额外的磁盘/ssd 空间来存储数据来提高查询性能。

    Microsoft SQL Server 用户可以这样声明索引:

    create index idx_name_age on table (id) include (name, age)
    

    在此索引中,name 和 age 的值与索引中的 id 一起出现,但索引未按包含的列排序。因此,更新索引需要更少的时间。

    如果id 是表的主键,则在 MySQL 的 InnoDB 或 SQL Server 中都不适用。该表本身是id 上的索引;它有时被称为聚集索引。但现在我们进入了太多细节。

    如果使用得当,覆盖索引可以显着提高查询性能。阅读https://use-the-index-luke.com/ 要获得帮助的索引,您必须设计它们以匹配您的查询。这是数据库优化艺术的重要组成部分。

    【讨论】:

      猜你喜欢
      • 2010-10-11
      • 2010-09-08
      • 1970-01-01
      • 2017-01-12
      • 2012-01-03
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多