如何索引 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 或...;

所以问题解决了,虽然我仍然不明白为什么优化器在第一次查询时遇到困难。

无论如何,感谢您的所有想法、想法和贡献,使我找到了解决方法。