如何索引 MySQL InnoDB table 以使用 select 进行查询......其中键入(此处有一些值)?
How to index a MySQL InnoDB table to query with select ... where key in ( some values here)?
我有一个mariadb 10.3服务器,下面table(使用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);
令牌 table 有 ~900k 行,我想在 IN ( )
子句中使用 2-300 个数字执行以下查询:
select token, nham, nspam from token where token in (1,2,3,4,...);
现在的问题是:查询执行的很慢,而且不会使用 token_idx1
:
+------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+
| 1 | SIMPLE | token | ref | token_idx1 | token_idx1 | 2 | const | 837534 | Using where |
+------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+
由于标记列已编入索引,我很惊讶解释 select 说优化器对 token_idx1
没有兴趣(并且查询需要很长时间,由于 ~30 秒完整 table 扫描)。
如何解决这个问题?我知道我可以在查询中使用 USE INDEX(token_idx1)
,但我会在没有这种 hack 的情况下解决它。
删除现有索引 token_idx1 并使用
重新创建
CREATE INDEX token_idx1 ON token(token) USING BTREE;
CREATE INDEX token_idx2 ON token(uid) USING BTREE;
解决方案是重写查询。因此,虽然这样的查询性能很差:
select token, nham, nspam from token where token in (1,2,3,4,...);
以下查询速度很快(即使 table 中不存在某些标记值):
select 来自令牌的令牌、nham、nspam,其中令牌=1 或令牌=2 或令牌=3 或...;
所以问题解决了,虽然我仍然不明白为什么优化器在第一次查询时遇到困难。
无论如何,感谢您的所有想法、想法和贡献,使我找到了解决方法。
我有一个mariadb 10.3服务器,下面table(使用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);
令牌 table 有 ~900k 行,我想在 IN ( )
子句中使用 2-300 个数字执行以下查询:
select token, nham, nspam from token where token in (1,2,3,4,...);
现在的问题是:查询执行的很慢,而且不会使用 token_idx1
:
+------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+ | 1 | SIMPLE | token | ref | token_idx1 | token_idx1 | 2 | const | 837534 | Using where | +------+-------------+-------+------+---------------+------------+---------+-------+--------+-------------+
由于标记列已编入索引,我很惊讶解释 select 说优化器对 token_idx1
没有兴趣(并且查询需要很长时间,由于 ~30 秒完整 table 扫描)。
如何解决这个问题?我知道我可以在查询中使用 USE INDEX(token_idx1)
,但我会在没有这种 hack 的情况下解决它。
删除现有索引 token_idx1 并使用
重新创建CREATE INDEX token_idx1 ON token(token) USING BTREE;
CREATE INDEX token_idx2 ON token(uid) USING BTREE;
解决方案是重写查询。因此,虽然这样的查询性能很差:
select token, nham, nspam from token where token in (1,2,3,4,...);
以下查询速度很快(即使 table 中不存在某些标记值):
select 来自令牌的令牌、nham、nspam,其中令牌=1 或令牌=2 或令牌=3 或...;
所以问题解决了,虽然我仍然不明白为什么优化器在第一次查询时遇到困难。
无论如何,感谢您的所有想法、想法和贡献,使我找到了解决方法。