什么是 MySQL 覆盖索引?

What is a MySQL covering index?

我看到documentation描述覆盖指数:

covering index
An index that includes all the columns retrieved by a query.

覆盖索引是不是特定索引?

我觉得覆盖指数是一种现象

如果我按照文档的描述,那么请看下面的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 是第一个语句中的覆盖索引,第二个不是。

所以我认为:覆盖指数是一种现象而不是一个指数

is the covering index is a specific index?

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

对于这个查询

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 值。

nameage 也出现在索引中,因为它们出现在 SELECT 子句中。因为它们在索引中,查询可以完全从索引中得到满足。这很好,因为它减少了从磁盘或 ssd 的读取:MySQL 没有在满足查询之前使用索引在主 table 中查找行。

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

这个查询

select id, name from table where id = 1

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

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

Microsoft SQL 服务器用户可以这样声明索引:

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

在此索引中,nameage 的值与索引中的 id 并存,但索引未按包含的列排序。因此,更新索引花费的时间更少。

如果 id 是 table 的主键,则 none 适用于 MySQL 的 InnoDB 或 SQL 服务器。 table 本身是 id 上的索引;它有时被称为聚簇索引。但是现在我们涉及的细节太多了。

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

假设 "covering" 是特定 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 并且 table 有 PRIMARY KEY(id),那么这些二级索引中的 none 是值得拥有的。

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 将(通常)选择 'smallest' 索引来进行计数。

另一个'rule'是为了避免冗余索引。

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