优化大表的简单SQL查询

时间:2014-06-05 11:51:01

标签: sql postgresql query-optimization

我有一个查询,其中一个表有大约1000万行,另外两个表在每个表中<20。

SELECT a.name, b.name, c.total
FROM smallTable1 a, smallTable2 b, largeTable c
WHERE c.id1 = a.id AND c.id2 = b.id;

largeTable包含(id, id1, id2, total)列和〜1000万行

smallTable1(id, name)

smallTable2(id, name)

现在需要5秒才能运行 有可能让它更快吗?

3 个答案:

答案 0 :(得分:2)

创建索引 - 它们是查询速度快的原因。如果没有索引,我们将无法使用仅限CPU的解决方案。

所以:

  1. 为SmallTable1(id)
  2. 创建索引
  3. 为SmallTable2(id)创建索引
  4. 为LargeTable(id1)和LargeTable(id2)
  5. 创建索引

    重要:您可以同时为多个列创建索引,例如此LargeTable(id1,id2)&lt; ---不要这样做,因为它没有意义你的情况。

    下一步,您的查询不是开箱即用的错误,但它不符合查询的最佳做法。关系数据库基于Set theory。因此,你必须考虑“带有弹珠的袋子”而不是“桌子中的细胞”。 粗略地说,您的初始查询转换为:

    1. 从LargeTable c,SmallTable1 a和SmallTable2 b
    2. 获取所有内容
    3. 现在,当您拥有所有这些信息时,找到c.id1 = a.id和c.id2 = b.id的项目; (这是你的5秒以上,因为这是半资源密集型的)
    4. Ambrish建议了正确的查询,使用它虽然这不会更快。

      为什么呢?因为最后,您仍然将表中的所有数据从数据库中提取出来。

      至于数据本身就是:1000万条记录并不是一张大得惊人的大表,但它也不小。在数据仓库中,star schema是标准。而且你基本上有一个星型模式。您实际面临的问题是必须在运行中计算结果并且需要时间。我告诉你的原因是因为在企业环境中,工程师每天都面临这个问题。解决方案是OLAP(基本上是预先计算,预先聚合,预先汇总,预先存在的所有数据)。然后最终用户只查询这个预先计算的数据并且查询看起来非常快,但它永远不会100%正确,因为OLTP之间存在延迟(在线事务性处理=日常数据库)和OLAP(在线分析处理=报告数据库) 这些索引将有助于查询WHERE id = 3等。但是当你交叉加入并基本上从数据库中提取所有内容时,它可能不会在你的情况下发挥重要作用。

      所以长话短说:如果您的唯一选择是查询,那么很难做出改进。

答案 1 :(得分:0)

在一种情况下,大表中的单独索引ID1ID2会产生较小的差异。如果有{9}}匹配ID1的9,000,000行和匹配SmallTable1.id的{​​{1}}的200行,而200是同时存在的唯一行,则您将仍在做几乎完整的表/索引扫描。如果是这种情况,在 {/ em> ID2 SmallTable2.id上创建索引应该可以加快速度,因为它可以找到带有索引的200行寻道。

如果可行,您可能希望在该索引中包含ID1,以使其成为该表的覆盖索引。

这个解决方案(假设它是一个)将是非常以数据为中心的,因此如果数据发生显着变化,执行将会改变。

无论您决定做什么,我建议您进行一次更改(创建索引或其他),然后检查执行计划。进行另一项更改并检查执行计划。进行另一项更改并检查执行计划。根据需要重复或倒回。

答案 2 :(得分:-1)

使用join而不是WHERE子句

SELECT a.name, b.name, c.total
FROM smallTable1 a join largeTable c on c.id1 = a.id
join smallTable2 b on c.id2 = b.id;

indexlargeTable(id1)

上创建largeTable(id2)