MySQL如何加快这个SELECT查询?

xen*_*ndi 4 mysql optimization select

我有一个超过900万行的非常大的表,在我的软件中,我需要在循环中快速对它进行选择查询.问题是查询需要将近4秒钟才能完成.这是一个查询(它们都是相似的,因为它们都有相同的WHERE子句,这使得它们变慢了:

SELECT MIN(id)
FROM `04c1Tg0M`
WHERE `tried` = 0;
Run Code Online (Sandbox Code Playgroud)

我正在使用已尝试的列作为布尔值.值为1或0.以下是该查询的EXPLAIN:

--------+--------------------------+
| id | select_type | table    | type  | possible_keys | key  | key_len | ref  | rows    | Extra                    |
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+
|  1 | SIMPLE      | 04c1Tg0M | index | NULL          | pdex | 158     | NULL | 9275107 | Using where; Using index |
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+
Run Code Online (Sandbox Code Playgroud)

这是表结构:

CREATE TABLE `04c1Tg0M` (
    `id` int(20) NOT NULL AUTO_INCREMENT,
    `username` varchar(50) NOT NULL,
    `tried` tinyint(1) DEFAULT '0',
    PRIMARY KEY (`id`),
    KEY `pdex` (`username`,`id`,`tried`)
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)

这是show indes的输出:

| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| 04c1Tg0M |          0 | PRIMARY  |            1 | id          | A         |     9275107 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            1 | username    | A         |     9275107 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            2 | id          | A         |     9275107 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            3 | tried       | A         |     9275107 |     NULL | NULL   | YES  | BTREE      |         |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
Run Code Online (Sandbox Code Playgroud)

这是来自查询的输出:

+---------+
| MIN(id) |
+---------+
|       1 |
+---------+
1 row in set (3.76 sec)
Run Code Online (Sandbox Code Playgroud)

我需要大幅缩短查询时间.任何帮助是极大的赞赏.

Mar*_*ers 6

你应该添加一个索引(tried, id).

您已经添加了索引,(username,id,tried)但此索引无法有效地用于您编写的查询,因为该字段tried不是索引中的第一项.


从手册页MySQL如何使用索引:

MySQL使用索引进行这些操作:

  • 查找特定索引列的值MIN()MAX()key_col.这是由预处理器优化的,该预处理器检查您是否正在使用索引WHERE key_part_N = constant之前出现的所有关键部分key_col.在这种情况下,MySQL对每个MIN()MAX()表达式执行单个键查找,并用常量替换它.如果所有表达式都替换为常量,则查询立即返回.例如:

    SELECT MIN(key_part2),MAX(key_part2)FROM tbl_name WHERE key_part1 = 10;

请特别注意,该WHERE条款必须是指发生列柱要为其计算MIN或者MAX,这就是为什么当前的指数不能有效地使用.


我需要在循环中快速对它进行选择查询

你确定需要循环查询吗?您是否考虑过将循环移动到数据库中?也许你真正需要的是一个加入?发送一个获取大量数据的查询比使用每次只获取少量数据的大量小查询更好.