SQL使用GROUP BY查询优化加入

时间:2017-10-22 08:05:53

标签: sql postgresql performance

我正在尝试优化以下查询。

 SELECT C.name, COUNT(DISTINCT I.id), COUNT(B.id)
   FROM Categories C, Items I, Bids B
  WHERE C.id = I.category
    AND I.id = B.item_id
  GROUP BY C.name
  ORDER BY 2 DESC, 3 DESC;
  • 类别是一张包含20条记录的小表。
  • 项目是一个包含超过50,000条记录的大表。
  • Bids是一个更大的表,有超过600,000条记录。

我有一个索引

Categories(name, id), Items(category), and Bids(item_id, id).

每个表的PRIMARY KEY为:Items(id), Categories(id), Bids(id)

是否有可能优化查询?非常感谢。

3 个答案:

答案 0 :(得分:0)

如果没有EXPLAIN (ANALYZE, BUFFERS)输出,这就是猜测。

查询非常简单,无法在那里进行优化。

  • 你弄错了正确的表格统计数据;检查EXPLAIN (ANALYZE)以查看PostgreSQL的估算是否正确。

  • 增加shared_buffers以便整个数据库适合RAM(如果可以的话)。

  • 增加work_mem,以便在内存中执行所有哈希和排序。

答案 1 :(得分:0)

你真的不是在扫描所有记录。

使用出价数据点击了多少项记录。我想象所有表都是完全扫描并且哈希加入,并且索引被忽略。

答案 2 :(得分:0)

您的查询似乎真的是锅炉板,我相信,根据您的表的大小,任何非真正低硬件的服务器都可以在心跳中运行此查询。但你总能让事情变得更好。从理论上讲,这是一个可以提高查询性能的优化列表:

  • 从理论上讲,你最大的低效率是计算表格的交叉积而不是加入它们。您可以使用以下连接重写查询:
...

FROM Items I 

INNER JOIN Bids B
ON I.id = B.item_id

INNER JOIN Categories C

ON C.id = I.category

...
  • 如果我们正在考虑所有性能方面,那么Items表类别的索引效率很低,因为您的索引只有20个映射到50K条目的条目。这是一个效率低下的索引,如果没有这个索引,你甚至可以获得更好的性能。但是,从实际的角度来看,这里还有很多其他的东西需要考虑,所以这可能不是什么大问题。
  • 您在Items表的ID列上没有索引,并且在该列上有索引可加快您的第一次加入。 (但是PostgreSQL在主键列上有默认索引,所以这也不是什么大问题)

此外,在查询开头添加explain analyze会显示PostgreSQL查询计划程序用于运行查询的计划。如果您对查询计划了解一两件事,我建议您查看其中的结果,以找出任何缺失的低效率。