为什么MySQL不能使用部分主键索引?

问题描述 投票:12回答:2

描述use of index extensions的MySQL文档,以下表为例,后面是查询:

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;

SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01';

InnoDB内部将索引k_d转换为包含最后的主键。也就是说,实际指数k_d将在(d, i1, i2),三列。

文档继续解释(强调我的):

在这种情况下,优化器不能使用主键,因为它包含列(i1,i2),查询不引用i2。相反,优化器可以在(d)上使用辅助索引k_d,执行计划取决于是否使用扩展索引。

我对以上陈述感到困惑。首先它说i1不足以使用两列(i1, i2)的主键索引。然后,在第二句中,它表示可以使用k_d上的指数(d, i1, i2),尽管只使用di1,而i2缺席。

我对MySQL中的索引以及其他SQL版本的一般理解是,如果索引中所有列的子集都存在,则可以使用索引的左侧部分,从左侧开始。

主键(聚簇)索引和非聚簇二级索引有什么不同,它允许后者使用部分索引,但前者不能?

mysql indexing clustered-index
2个回答
9
投票

您链接到的页面上的文档部分不准确。

演示,在MySQL 5.7.21上运行:

mysql [localhost] {msandbox} (test) > 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;

mysql [localhost] {msandbox} (test) > explain SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01';
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | PRIMARY,k_d   | PRIMARY | 4       | const |    1 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+

此查询选择PRIMARY索引,您可以看到key_len为4,证明它将仅使用32位INT列中的一个。

使用InnoDB表时,MySQL通常更喜欢使用PRIMARY索引(聚簇索引),因为它比使用二级索引更有效。


0
投票

在这种情况下

WHERE i1 = 3 AND d = '2000-01-01';

我更愿意明确地说INDEX(d, i1)(或INDEX(i1, d))。我的理由是,我告诉读者我考虑了索引,并意识到这对查询来说是最好的。这将是一个“覆盖”指数,因此更快一点。

当然,你所拥有的INDEX(d)应该相当于INDEX(d, i1, i2),它应该被有效和有效地使用。至于为什么,我猜想在优化器中有疏忽。

至于文档,有一些措辞不佳的地方。他们欢迎来自bugs.mysql.com的文档批评。

© www.soinside.com 2019 - 2024. All rights reserved.