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

Kar*_*. V 14 mysql indexing primary-key

Assets在InnoDB引擎上有一个表定义为:

CREATE TABLE Assets (
qid SMALLINT(5) NOT NULL,
sid BIGINT(20) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (sid,qid),
KEY sid (sid)
);
Run Code Online (Sandbox Code Playgroud)

我正在运行以下查询:

SELECT COUNT(*) FROM Assets WHERE sid>10000;
Run Code Online (Sandbox Code Playgroud)

在我的机器上,此查询大约需要30秒,表中有2百万个条目.现在,如果我修改查询以使用索引,结果差异很大:

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

所以这些是我的问题:

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

  2. 如果NO INDEX实际上没有使用主键作为索引,那么是USE INDEX(PRIMARY)什么原因导致它具有相同的运行时间NO INDEX

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

原谅长篇文章,但我想让它开放讨论.


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

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

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

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

对于离散键,行数可以相同,但扫描的索引要小得多(由指示的字段组成),这会占用较少数量的磁盘块,因此运行速度要快得多.我假设这也是使用USE INDEX(cid)和使用主键作为索引的差异的原因,两者都具有相同的字段.

Luk*_*uke 1

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

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

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

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

我只是对 use(primary) 强制 mysql 不使用索引有点困惑,但这可能与你的 mysql 版本有关(一个错误?)。

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

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

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

华泰