2014-10-06 26 views
0

审查有没有像MySQL的许多行通过简单查询

CREATE TABLE `tb_tag_article` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `tag_id` int(16) NOT NULL, 
    `article_id` int(16) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `key_tag_id_article_id` (`tag_id`,`article_id`) USING BTREE, 
) ENGINE=InnoDB AUTO_INCREMENT=365944 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

当我这样的查询表tb_tag_article,结果是。

SELECT count(*) FROM tb_tag WHERE tag_id = 43 

但当我解释这样的查询

EXPLAIN SELECT count(*) FROM tb_tag WHERE tag_id = 43 

检查的行是。

+------+-------------+----------------+------+-----------------------+-----------------------+---------+-------+-------+-------------+ 
| id | select_type | table   | type | possible_keys   | key     | key_len | ref | rows | Extra  | 
+------+-------------+----------------+------+-----------------------+-----------------------+---------+-------+-------+-------------+ 
| 1 | SIMPLE  | tb_tag_article | ref | key_tag_id_article_id | key_tag_id_article_id | 4  | const | 13634 | Using index | 
+------+-------------+----------------+------+-----------------------+-----------------------+---------+-------+-------+-------------+ 

查询使用索引,但检查行数大于实际数据数。 什么问题?

+2

让我猜:你的桌子包含13k行和5k他们有tag_id 43 – 2014-10-06 14:51:41

回答

0

问:什么问题?

- 答:它看起来没有任何问题。

EXPLAIN输出中“rows”列的值是一个估计值,而不是确切的数字。

编号:http://dev.mysql.com/doc/refman/5.5/en/explain-output.html


为了评估每一个可能的存取路径的“成本”,只需要优化器估计,以比较使用与全扫描上的索引范围扫描操作的效率表中所有行的数量。优化器不需要表中总数行的“精确”计数,也不需要满足谓词的行数。

对于这个简单的查询,MySQL只会考虑一些可能的计划。

并且13684的估计值与行的确切数量相差不远。它是2.5倍,但MySQL提出了正确的执行计划:使用索引,而不是检查表中的每一行。

没有问题。

0

从MySQL参考(http://dev.mysql.com/doc/refman/5.0/en/explain-output.html#explain_rows):

rows列指出MySQL认为它必须 检查以执行查询的行数。

对于InnoDB表,这个数字是一个估计值,并不总是精确的 。

也可能是因为它必须分析索引,它会考虑索引中的记录数加上表中记录的数量。但这只是一个假设。

此外,它看起来像MySQL 5.1中的一个错误,解释行估计导致数字被忽略:http://bugs.mysql.com/bug.php?id=53761根据您的版本,这可能解释了一些奇怪之处。

从文档中获得的主要结果似乎是用一粒盐对EXPLAIN行列进行树化处理。

+0

非常感谢。 – chris 2014-10-06 15:20:00