4

我想做这样的计数(例如,不是真的数狗):

SELECT COUNT(*)
FROM dogs AS d INNER JOIN races AS r ON d.race_id = r.race_id
    LEFT INNER colors AS c ON c.color_id = r.color_id
WHERE d.deceased = 'N'

MyISAM 表中有 130,000 条狗。Races 有 1,500 条记录,是一个有 9 列的 InnoDB 表,colors 有 83 条记录,也是 InnoDB,有两列(id、name)。*_id 列都是主键,我在“外”键dogs.race_id 和races.color_id 上有索引,并且在dogs.deased 上有索引。没有提到的列可以是NULL

# mysql --version
mysql  Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (i486) using readline 5.2

现在的问题是:在我的 PhpMyAdmin 中,这个查询需要 1.8 秒(带有SQL_NO_CACHE),计数结果为 64,315。更改COUNT(*)COUNT(d.dog_id)COUNT(d.deceased)也使查询运行 1.8 秒,结果相同。

但是当我删除COUNT()and just do SELECT *orSELECT dog_id时,运行大约需要 0.004 秒(然后用类似的东西计算结果mysql_num_rows())。

怎么会这样?我怎样才能使COUNT()工作更快?

编辑:在EXPLAIN下面添加了

EXPLAIN SELECT COUNT(*)
FROM dogs AS d INNER JOIN races AS r ON d.race_id = r.race_id
    INNER JOIN colors AS c ON c.color_id = r.color_id
WHERE d.deceased = 'N'

给我:

+----+-------------+-------+-------+------------------+----------+---------+----------------------+------+-------------+
| id | select_type | table | type  | possible_keys    | key      | key_len | ref                  | rows | Extra       |
+----+-------------+-------+-------+------------------+----------+---------+----------------------+------+-------------+
|  1 | SIMPLE      | c     | index | color_id         | color_id | 4       | NULL                 |   83 | Using index | 
|  1 | SIMPLE      | r     | ref   | PRIMARY,color_id | color_id | 4       | database.c.color_id  |   14 | Using index | 
|  1 | SIMPLE      | d     | ref   | race_id,deceased | race_id  | 4       | database.r.race_id   |  123 | Using where | 
+----+-------------+-------+-------+------------------+----------+---------+----------------------+------+-------------+
4

3 回答 3

1

MySQL 优化器仅在需要时才进行全表扫描,因为列可以为 NULL,这意味着如果该列未定义为 NOT NULL,则其中可能存在一些 NULL 值,因此 MySQL 必须执行表扫描才能找到。如果您的列可以d.dog_id为空?尝试在另一个不可为空的列上运行计数,这应该为您提供比 count(*) 更好的性能。

于 2013-04-09T09:50:15.120 回答
0

创建索引以使您的计数更快:

CREATE INDEX ix_temp ON dogs (d.race_id)
INCLUDE (columns needed for the query)
于 2013-04-09T09:59:24.260 回答
0

尝试设置索引dogs.deceased并使用SELECT COUNT(*) ... USE INDEX my_index_name.

于 2013-04-09T09:51:51.640 回答