计算多个表中的行会导致大的延迟

时间:2013-09-16 14:02:05

标签: mysql sql

我有3个主要包含字符串数据和唯一id列的表:

categories ~45 rows
clientfuncs ~800 rows
serverfuncs ~600 rows

所有表都有唯一的主AI列'id'。 我尝试在一个查询中计算行数:

SELECT COUNT(categories.id), COUNT(serverfuncs.id), COUNT(clientfuncs.id) FROM categories, serverfuncs, clientfuncs

需要1.5 - 1.7 s。

当我尝试

SELECT COUNT(categories.id), COUNT(serverfuncs.id) FROM categories, serverfuncs

SELECT COUNT(categories.id), COUNT(clientfuncs.id) FROM categories, clientfuncs

SELECT COUNT(clientfuncs.id), COUNT(serverfuncs.id) FROM clientfuncs, serverfuncs

,需要0.005 - 0.01 s。 (应该是)

有人可以解释,这是什么原因?

4 个答案:

答案 0 :(得分:6)

您正在进行45 * 800 * 600行的交叉联接,当您检查计数结果时,您会注意到: - )

请改为尝试:

SELECT 
  (SELECT COUNT(*) FROM categories), 
  (SELECT COUNT(*) FROM serverfuncs), 
  (SELECT COUNT(*) FROM clientfuncs);

答案 1 :(得分:5)

查询正在执行cartesian product,因为没有应用连接条件,因此:

1 query : 800*600*45 = 21,6 mil
2 query : 45*600     = 27 k
3 query : 45*800 ...

答案 2 :(得分:2)

这是因为您的查询正在加入表(查询的最后部分中的逗号是连接的简写),而不是单独计算它们。因此,只有两个表的查询会更快。

答案 3 :(得分:2)

首先,您是否真的想在FROM子句中使用三个表来计算特定于每个表的计数?这将导致SELECT语句生成三个表的笛卡尔乘积,这将导致计算计数的总行数为45 x 800 x 600。因此,会计算很多重复的categories.id值,其他计数也是如此。在任何情况下,如果在FROM子句中使用前两个表,则笛卡尔积只包含45 X 800行,这比三个表生成的行要小得多。因此,具有两个表的查询要快得多。在这种情况下,主键是没用的。

最好使用三个不同的语句来计算每个表的计数。

如果您仍坚持一次性获取计数,则可以使用以下语法:

SELECT (SELECT COUNT(categories.id) FROM categories), 
       (SELECT COUNT(serverfuncs.id) FROM serverfuncs), 
       (SELECT COUNT(clientfuncs.id) FROM clientfuncs);

如果您的RDBMS支持没有FROM子句的SELECT语句。这些将给出正确的计数,并且会非常快。