Mysql - where子句比完全扫描慢

时间:2011-07-17 04:37:51

标签: mysql

查询A

Select id from jobs;

| 55966 |
| 55971 |
+-------+
10705 rows in set (0.00 sec)

查询B

Select id from jobs where status = 0;
| 55966 |
| 55971 |
+-------+
7933 rows in set (**20.22 sec**)

状态指数。

mysql> explain select id from jobs where status = 0;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | jobs  | ALL  | status        | NULL | NULL    | NULL | 10705 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.01 sec)


mysql> show profile for query 1;
+--------------------------------+-----------+
| Status                         | Duration  |
+--------------------------------+-----------+
| starting                       |  0.000023 |
| checking query cache for query |  0.000039 |
| checking permissions           |  0.000006 |
| Opening tables                 |  0.000008 |
| System lock                    |  0.000004 |
| Table lock                     |  0.000016 |
| init                           |  0.000021 |
| optimizing                     |  0.000007 |
| statistics                     |  0.000904 |
| preparing                      |  0.000023 |
| executing                      |  0.000003 |
| Sending data                   | 19.751547 |
| end                            |  0.000009 |
| query end                      |  0.000002 |
| freeing items                  |  0.001561 |
| storing result in query cache  |  0.000122 |
| logging slow query             |  0.000002 |
| logging slow query             |  0.000002 |
| cleaning up                    |  0.000003 |
+--------------------------------+-----------+

mysql> show index from jobs;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

| jobs  |          1 | status   |            1 | status      | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
| jobs  |          1 | date     |            1 | dateinit    | A         |        1784 |     NULL | NULL   | YES  | BTREE      |         |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
10 rows in set (0.02 sec)

我不明白为什么查询B需要20秒,而查询A需要0。 “状态”索引。 prod和dev的结果相同。服务器

3 个答案:

答案 0 :(得分:1)

0.00秒听起来像查询可能已缓存。话虽如此,对表的id的查询可以直接从主键索引回答(即,根本不查看表数据!),而查询带有WHERE子句要求数据库实际读取行。

答案 1 :(得分:1)

尝试将索引更改为(status, id)

在我看来,你没有id

的任何索引

ANSI standard(查找“Scalar expressions 125”)指出COUNT(*)给出了表的行数:它旨在从一开始就进行优化。

  

如果指定COUNT(*),则结果为T的基数。

这就是COUNT(*)COUNT(id)快得多的原因。 COUNT(*)可以使用status索引。 COUNT(id)将不使用此索引,并且没有其他有效索引

什么是聚集索引,什么是PK?你有两个(即使是相同的索引),对吧?

答案 2 :(得分:0)

status上有一个索引,但是一旦MySQL确定哪些行有status = 0,就会有一个调用,每行都要找到它的id。如果你create index idx_jobs_status_id on jobs (status, id);我预测20秒会消失。