【发布时间】:2018-12-28 20:44:54
【问题描述】:
我有一个 mariadb 10.3 服务器,以及下表(使用 InnoDB 存储引擎):
create table if not exists token (
`token` bigint unsigned not null,
`uid` smallint unsigned not null default 0,
`nham` int default 0,
`nspam` int default 0,
`timestamp` int unsigned default 0
) Engine=InnoDB;
create index token_idx1 on token(token);
create index token_idx2 on token(uid);
令牌表有大约 900k 行,我想在 IN ( ) 子句中使用 2-300 个数字执行以下查询:
select token, nham, nspam from token where token in (1,2,3,4,...);
现在的问题是:查询执行得很慢,它不会使用token_idx1:
由于对令牌列进行了索引,我很惊讶 explain select 说优化器对 token_idx1 不感兴趣(并且查询需要很长时间,由于全表扫描,大约需要 30 秒)。
如何解决这个问题?我知道我可以在查询中使用 USE INDEX(token_idx1),但我会在没有这种 hack 的情况下解决它。
【问题讨论】:
-
我无法想象包含 300 个元素的 in 语句会很快。你能把这些放到一个表中,然后用一个连接代替吗?
-
不确定这是否有帮助,但我对我的一张表进行了一些测试,该表在列上有类似的索引。我只测试了 IN 子句,但得到了有趣的结果。当我使用只有有效匹配的列表时,它运行得非常快,但是当我输入无效时,它似乎扫描了整个表。 EXPLAIN 验证了这种行为。
-
出了点问题——
key_len = 2,但token是BIGINT UNSIGNED(8 个字节)。请验证CREATE TABLE、索引和说明。 -
你真的需要一个
PRIMARY KEY在桌子上。 -
很遗憾,我无法将这 300 个项目放在单独的表中。如果该列被索引(原样),那么我希望即使有 300 个项目的查询也会非常快。请参阅下面的解决方案。
标签: mysql select mariadb innodb explain