mysql - MySQL 中的索引和使用主键作为索引

标签 mysql indexing primary-key

我有一张 table Assets在 InnoDB 引擎上定义为:

CREATE TABLE Assets (
qid SMALLINT(5) NOT NULL,
sid BIGINT(20) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (sid,qid),
KEY sid (sid)
);

我正在运行以下查询:

SELECT COUNT(*) FROM Assets WHERE sid>10000;

在我的机器上,此查询需要大约 30 秒,表中有 200 万个条目。现在,如果我修改查询以使用索引,结果将大相径庭:

SELECT COUNT(*) FROM Assets USE INDEX(<index>) WHERE sid>10000;
  • NO INDEX : 没有明确的 USE INDEX ,即第一个 SELECT查询:30 秒
  • KEY sid (sid) : 1.5 秒
  • KEY cid (sid,qid) : 1.5 秒
  • PRIMARY :我用过USE INDEX(PRIMARY)在查询中。 : 30 秒

所以这些是我的问题:

  1. 我认为查询会自动使用主键作为其索引,基于 this .然而 USE INDEX (cid) 之间存在重大差异和 NO INDEX .有什么不同?另外,我如何明确指定主键作为索引?

  2. 如果 NO INDEX实际上并没有使用主键作为索引,USE INDEX(PRIMARY) 是做什么的?这样做会使它的运行时间与 NO INDEX 相同?

  3. USE INDEX(sid) 之间是否存在差异(不仅仅是性能方面的差异)?和 USE INDEX(cid)在仅按 sid 过滤的查询中?

请原谅这篇冗长的帖子,但我想让它开放讨论。


好的,这是我到目前为止发现的:

首先,有人告诉我 key 设置应该是:PRIMARY KEY(qid,sid), KEY(sid)PRIMARY KEY(sid,qid), KEY(qid) .我真的不明白其中的区别。如果有人这样做,请告诉我。

其次,KEY sid ( sid ) 引用的索引页比较大的键少得多,因此它往往更快。至于使用 PRIMARY KEY 作为索引和使用正确的 KEY(即使它们使用相同的字段)之间的区别,我被告知是这样的:

主键用主键的字段索引整个表数据。这意味着 PRIMARY KEY 和数据存储在一起。因此,使用 PRIMARY KEY 的查询必须遍历整个表数据,即使索引也会陷入无法缓存的大型表中。

对于离散键,行数可能相同,但扫描的索引(由指示的字段组成)要小得多,这会命中较少数量的磁盘 block ,因此运行得更快。我假设这也是使用 USE INDEX(cid) 不同的原因并使用主键作为索引,两者具有相同的字段。

最佳答案

根据我的经验,拥有一个索引是另一个索引的子集往往会减慢速度。但你的里程可能会有所不同,因为在处理索引时你必须考虑很多事情。

例如,如果您经常阅读并且很少更改数据,那么拥有许多索引可能会帮助您更多;如果您的操作涉及大量插入/更新/删除,那么索引过多可能会减慢您的速度。

如果您的主键是 (sid, qid),那么我认为不适合使用引擎可以检索的另一个键 (sid) 作为 PK 的前缀。 如果我要利用它,我宁愿在 qid 上添加一个索引 - 也就是说,如果我对该字段有一些查询过滤或排序,或者我在该字段上有一些 JOIN..

根据主键上字段的顺序,我通常会尝试确定它们将如何在我的查询中使用:如果我的所有查询都使用 sid 并且一些同时使用 sid 和 qid,则选择 (sid,启德);如果他们都使用qid并且只有一些也使用sid,则选择(qid, sid);如果他们碰巧使用 sid 或 qid,则有一个 PK (sid, qid) 和另一个 key (qid),以便使用这两个字段的查询将使用您的 PK,仅使用 sid 的查询也会发生同样的情况,最后仅使用 qid 的用户将使用 (qid) 键。

我只是对 use(primary) 强制 mysql 不使用索引有点困惑,但这可能是与您的 mysql 版本相关的东西(错误?)..

您可以在此处找到有关索引提示的一些提示: http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

一般来说尽量不要过多地使用索引提示,优化器通常做得很好!如果没有,可能是某处存在缺陷,或者它只是认为表扫描更快,因为索引的选择性不够。

此外,您有时可能需要优化表来刷新索引统计信息。但由于您使用的是 InnoDB,因此可能并非如此...

HTH

关于mysql - MySQL 中的索引和使用主键作为索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10205301/

相关文章:

mysql - 我可以创建一个没有 PK 的 InnoDB 表吗?如果是的话,是否会使用二级索引作为聚集索引?

c# - Entity Framework 非标识 - 无法将值 NULL 插入列 'ID'

mysql - 选择不同的,在行尾显示计数

php - 将 mysql_data_seek 函数更改为 PDO

Python:从字符串中检测单词并找到它的位置

arrays - matlab:在元素之后插入元素?

javascript - 索引键上的 cursor.skip() 总是更快吗?

php - 如何在另一个表中抓取主键并将其放入外键? PHP, MySQL

mysql - 获取用户的 SQL 查询

mysql - Laravel 或Where 给出意想不到的结果