我有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。 (应该是)
有人可以解释,这是什么原因?
答案 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语句。这些将给出正确的计数,并且会非常快。