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

时间:2018-09-03 08:47:49

标签: mysql indexing clustered-index

描述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),但可以使用d 上的索引i1 i2不存在时使用。

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

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

2 个答案:

答案 0 :(得分:9)

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

演示,在MySQL 5.7.21上运行:

<div class="wrapper">
<div class="div1"></div>
<div class="div2"></div>
</div>

此查询选择PRIMARY索引,您可以看到{ path:'/profile/:name', component: Profile, meta: { title: route.param.name + 'place' } } 为4,证明它仅使用32位INT列之一。

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

答案 1 :(得分:0)

在这种情况下

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

我更愿意明确地INDEX(d, i1)(或INDEX(i1, d))。我的理由是,我告诉读者我已经考虑过索引,并意识到这最适合查询。这将是一个“覆盖”索引,因此速度更快。

当然,您拥有的INDEX(d)应该等同于INDEX(d, i1, i2),应该有效地使用它。至于原因,我猜想是优化器中的一个疏忽。

对于文档,有一些措辞不佳的地方。他们欢迎在bugs.mysql.com上对文档进行评论。