InnoDB
automatically extends each secondary index by appending the primary key columns to it. InnoDB
通过向每个辅助索引添加主键列来自动扩展它。Consider this table definition:考虑这个表定义:
CREATE TABLE t1 ( i1 INT NOT NULL DEFAULT 0, i2 INT NOT NULL DEFAULT 0, d DATE DEFAULT NULL, PRIMARY KEY (i1, i2), INDEX k_d (d) ) ENGINE = InnoDB;
This table defines the primary key on columns 此表定义了列(i1, i2)
. (i1, i2)
上的主键。It also defines a secondary index 它还定义了列k_d
on column (d)
, but internally InnoDB
extends this index and treats it as columns (d, i1, i2)
.(d)
上的二级索引k_d
,但InnoDB
在内部扩展了该索引并将其视为列(d, i1, i2)
。
The optimizer takes into account the primary key columns of the extended secondary index when determining how and whether to use that index. 优化器在确定如何以及是否使用该索引时,会考虑扩展辅助索引的主键列。This can result in more efficient query execution plans and better performance.这可以产生更高效的查询执行计划和更好的性能。
The optimizer can use extended secondary indexes for 优化器可以将扩展的二级索引用于ref
, range
, and index_merge
index access, for Loose Index Scan access, for join and sorting optimization, and for MIN()
/MAX()
optimization.ref
、range
和index_merge
索引访问、松散索引扫描访问、连接和排序优化以及MIN()
/MAX()
优化。
The following example shows how execution plans are affected by whether the optimizer uses extended secondary indexes. 下面的示例显示了优化器是否使用扩展的二级索引对执行计划的影响。Suppose that 假设t1
is populated with these rows:t1
中填充了以下行:
INSERT INTO t1 VALUES (1, 1, '1998-01-01'), (1, 2, '1999-01-01'), (1, 3, '2000-01-01'), (1, 4, '2001-01-01'), (1, 5, '2002-01-01'), (2, 1, '1998-01-01'), (2, 2, '1999-01-01'), (2, 3, '2000-01-01'), (2, 4, '2001-01-01'), (2, 5, '2002-01-01'), (3, 1, '1998-01-01'), (3, 2, '1999-01-01'), (3, 3, '2000-01-01'), (3, 4, '2001-01-01'), (3, 5, '2002-01-01'), (4, 1, '1998-01-01'), (4, 2, '1999-01-01'), (4, 3, '2000-01-01'), (4, 4, '2001-01-01'), (4, 5, '2002-01-01'), (5, 1, '1998-01-01'), (5, 2, '1999-01-01'), (5, 3, '2000-01-01'), (5, 4, '2001-01-01'), (5, 5, '2002-01-01');
Now consider this query:现在考虑这个问题:
EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'
The execution plan depends on whether the extended index is used.执行计划取决于是否使用扩展索引。
When the optimizer does not consider index extensions, it treats the index 当优化器不考虑索引扩展时,它只将索引k_d
as only (d)
. k_d
视为(d)
。EXPLAIN
for the query produces this result:EXPLAIN
查询将生成以下结果:
mysql> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ref
possible_keys: PRIMARY,k_d
key: k_d
key_len: 4
ref: const
rows: 5
Extra: Using where; Using index
When the optimizer takes index extensions into account, it treats 当优化器考虑索引扩展时,它将k_d
as (d, i1, i2)
. k_d
视为(d, i1, i2)
。In this case, it can use the leftmost index prefix 在这种情况下,它可以使用最左边的索引前缀(d, i1)
to produce a better execution plan:(d, i1)
来生成更好的执行计划:
mysql> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ref
possible_keys: PRIMARY,k_d
key: k_d
key_len: 8
ref: const,const
rows: 1
Extra: Using index
In both cases, 在这两种情况下,key
indicates that the optimizer uses secondary index k_d
but the EXPLAIN
output shows these improvements from using the extended index:key
表示优化器使用二级索引k_d
,但EXPLAIN
输出显示了使用扩展索引的这些改进:
key_len
goes from 4 bytes to 8 bytes, indicating that key lookups use columns d
and i1
, not just d
.key_len
从4字节变为8字节,表示键查找使用列d
和i1
,而不仅仅是d
。
The ref
value changes from const
to const,const
because the key lookup uses two key parts, not one.ref
值从const
更改为const, const
,因为键查找使用两个键部分,而不是一个。
The 行数从5减少到1,这表明rows
count decreases from 5 to 1, indicating that InnoDB
should need to examine fewer rows to produce the result.InnoDB
应该需要检查更少的行来生成结果。
The Extra
value changes from Using where; Using index
to Using index
. Extra
值从Using where; Using index
变为Using index
。This means that rows can be read using only the index, without consulting columns in the data row.这意味着可以仅使用索引来读取行,而无需查询数据行中的列。
Differences in optimizer behavior for use of extended indexes can also be seen with 使用扩展索引时优化器行为的差异也可以通过SHOW STATUS
:SHOW STATUS
看到:
FLUSH TABLE t1; FLUSH STATUS; SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'; SHOW STATUS LIKE 'handler_read%'
The preceding statements include 前面的语句包括FLUSH TABLES
and FLUSH STATUS
to flush the table cache and clear the status counters.FLUSH TABLES
和FLUSH STATUS
,用于刷新表缓存和清除状态计数器。
Without index extensions, 如果没有索引扩展,SHOW STATUS
produces this result:SHOW STATUS
将生成以下结果:
+-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 5 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | +-----------------------+-------+
With index extensions, 通过索引扩展,SHOW STATUS
produces this result. SHOW STATUS
生成此结果。The Handler_read_next
value decreases from 5 to 1, indicating more efficient use of the index:Handler_read_next
值从5减小到1,表示索引的使用效率更高:
+-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 1 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | +-----------------------+-------+
The use_index_extensions
flag of the optimizer_switch
system variable permits control over whether the optimizer takes the primary key columns into account when determining how to use an InnoDB
table's secondary indexes. optimizer_switch
系统变量的use_index_extensions
标志允许控制优化器在确定如何使用InnoDB
表的二级索引时是否考虑主键列。By default, 默认情况下,启用use_index_extensions
is enabled. use_index_extensions
。To check whether disabling use of index extensions can improve performance, use this statement:要检查禁用索引扩展是否可以提高性能,请使用以下语句:
SET optimizer_switch = 'use_index_extensions=off';
Use of index extensions by the optimizer is subject to the usual limits on the number of key parts in an index (16) and the maximum key length (3072 bytes).优化器对索引扩展的使用受索引中键部分数量(16)和最大键长度(3072字节)的通常限制。