我想做这样的计数(作为一个例子,不是真的算狗):
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表,颜色有83条记录,也是InnoDB,有两列(id,name)。
* _id列都是主键,我在'外键'上有索引dogs.race_id和races.color_id,我有一个关于dogs.deceased的索引。所提到的列都不能是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()
并且只执行SELECT *
或SELECT 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 |
+----+-------------+-------+-------+------------------+----------+---------+----------------------+------+-------------+
答案 0 :(得分:1)
MySQL Optimizer仅在需要时执行全表扫描,因为列可以为NULL,这意味着如果列未定义为NOT NULL,则可能会有一些NULL值,因此MySQL必须执行表扫描找出。如果您的列d.dog_id
可以为空?尝试在另一个不可为空的列上运行计数,这应该为您提供比count(*)更好的性能。
答案 1 :(得分:0)
尝试在dogs.deceased
上设置索引并使用SELECT COUNT(*) ... USE INDEX my_index_name
。
答案 2 :(得分:0)
创建索引以加快计算速度:
CREATE INDEX ix_temp ON dogs (d.race_id)
INCLUDE (columns needed for the query)