【发布时间】:2012-04-29 14:57:23
【问题描述】:
我在 InnoDB 引擎上有一个表 Assets,定义为:
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 秒
所以这些是我的问题:
我认为查询会自动使用主键作为索引,基于this。然而
USE INDEX (cid)和NO INDEX之间还是有很大区别的。有什么不同?另外,我如何明确地将主键作为索引?如果
NO INDEX实际上并没有使用主键作为索引,那么USE INDEX(PRIMARY)做了什么导致它与NO INDEX具有相同的运行时间?在仅按
sid过滤的查询中,USE INDEX(sid)和USE INDEX(cid)之间是否存在差异(不仅仅是性能方面的差异)?
请原谅这篇长文,但我想让它公开讨论。
好的,这是我目前发现的:
首先,有人告诉我密钥设置应该是: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) 和使用主键作为索引不同的原因,两者具有相同的字段。
【问题讨论】:
-
附注:如果你有
PRIMARY KEY (sid,qid),那么KEY sid (sid)没有意义 -
PS:请给
SELECT COUNT(*) FROM Assets WHERE sid>10000写EXPLAIN -
总共 2M 行中有多少行带有
sid>10000?如果它超过〜30%,那么mysql认为fullscan更便宜。这就是强制索引有帮助的原因 -
是的,超过 30%。如果我将其设置在中间标记(100 万)左右,则查询大约需要 20 秒。
-
如果您将结果集(通过在
sid>10000中指定更大的值)减少到大约 25-30% - 它是否会在没有提示的情况下更快地工作?
标签: mysql indexing primary-key