2

我有 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 秒。

当我尝试

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

4 回答 4

6

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

试试这个:

SELECT 
  (SELECT COUNT(*) FROM categories), 
  (SELECT COUNT(*) FROM serverfuncs), 
  (SELECT COUNT(*) FROM clientfuncs);
于 2013-09-16T14:07:06.583 回答
5

查询正在做笛卡尔积,因为没有应用连接条件,所以:

1 query : 800*600*45 = 21,6 mil
2 query : 45*600     = 27 k
3 query : 45*800 ...
于 2013-09-16T14:06:14.697 回答
2

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

于 2013-09-16T14:08:24.420 回答
2

首先,您真的想在 FROM 子句中使用三个表来计算每个表特定的计数吗?这将导致 SELECT 语句生成三个表的笛卡尔积,这将产生 45 x 800 x 600 的总行数,从中计算计数。因此,将计算 category.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 语句。这些将给出正确的计数并且会非常快。

于 2013-09-16T14:19:23.043 回答