mysql myisam 引擎中的主键是否隐式存储在其他键中?

Is the primary key stored implicitly in other keys in mysql myisam engine?

我的问题:想象一个有数百万行的 table,比如

CREATE TABLE a {
id INT PRIMARY KEY,
column2..,
column3..,
many other columns..
..
INDEX (column2);

和这样的查询:

SELECT id FROM a WHERE column2 > 10000 LIMIT 1000 OFFSET 5000;

我的问题:mysql 只使用索引 "column2"(因此主键 id 隐式存储为其他索引中的引用),还是必须获取所有行才能获取还有选择用于输出的id?在那种情况下,使用声明为的键查询应该快得多:

INDEX column2(column2, id)

需要 column2 上的索引。您在索引中使用 id 的建议将阻止 table 扫描并且应该非常有效。

此外,假设 column2 是一个连续序列,这样做会更快:

SELECT id FROM a WHERE column2 > 15000 LIMIT 1000;

这是因为要使用偏移量,它只需扫描接下来的 5000 条记录(MySQL 没有意识到您实际上正在偏移 column2)。

简答:否

长答案:

MyISAM与InnoDB不同,对每个索引的叶子节点中的数据有一个"pointer",包括那个PRIMARY KEY.

所以,INDEX(col2) 本质上是 INDEX(col2, ptr)INDEX(id) 的同上是 INDEX(id, ptr)

"pointer" 是 .MYD 文件中的字节偏移量(DYNAMIC)或记录号(FIXED)。在任何一种情况下,指针都会将 "seek" 指向 .MYD 文件。

指针默认为 6 字节数字,允许大量行。它可以通过设置进行更改,以保存 space 或允许更大的行数。

对于您的特定查询,INDEX(col2, id) 是最优的,"covering"。对于 MyISAM,它优于 INDEX(col2),但对于 InnoDB,它们是等效的,因为 InnoDB 在每个二级索引中隐式地具有 PK。

查询必须扫描至少 5000+1000 行,至少在索引的 BTree 中。

请注意,InnoDB 的 PRIMARY KEY 与数据聚类,但 MyISAM 的 PRIMARY KEY 是一个单独的 BTree,就像其他二级索引一样。

你真的应该考虑转向 InnoDB;今天几乎没有理由使用 MyISAM。