如何使用LEFT JOIN编写查询以获得更高的性能

时间:2013-07-26 05:52:48

标签: sql oracle

我试着理解如何使用大量JOIN子句来纠正写大查询。 这些查询的性能是否相同?

/*Sql 1*/
SELECT G.ID, T1.QUANTITY, T2.QUANTITY
 FROM GOODS G
LEFT JOIN
/*First subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM MY_TABLE_1
GROUP BY GOOD_ID
) T1 ON G.ID = T1.GOOD_ID
LEFT JOIN
/*Second subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
GROUP BY GOOD_ID
FROM MY_TABLE_2
) T2 ON G.ID = T2.GOOD_ID
/*and so on....Next same subqueries*/
WHERE G.ID IN (1, 2, 3, 4);

在下一个查询中,在所有连接子查询中设置相同的WHERE子句,并在INNER CLAUSE外部替换LEFT JOIN子句。这是一个好的解决方案吗?还是oracle优化器自动制作这样的东西?

/*Sql 2*/
SELECT G.ID, T1.QUANTITY, T2.QUANTITY
 FROM GOODS G
INNER JOIN
/*First subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM GOODS G
LEFT JOIN MY_TABLE_1 M ON M.GOOD_ID = G.ID
WHERE G.ID IN (1, 2, 3, 4);
GROUP BY GOOD_ID
) T1 ON G.ID = T1.GOOD_ID
INNER JOIN
/*Second subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM GOODS G
LEFT JOIN MY_TABLE_2 M ON M.GOOD_ID = G.ID
WHERE G.ID IN (1, 2, 3, 4);
GROUP BY GOOD_ID
) T2 ON G.ID = T2.GOOD_ID
/*and so on....Next same subqueries*/
WHERE G.ID IN (1, 2, 3, 4);

3 个答案:

答案 0 :(得分:1)

查询性能取决于很多方面,包括:

  • 所涉及的表格的相对大小
  • 是否存在涵盖连接列和过滤条件的索引
  • 数据库中表统计信息的货币
  • 查询的编写方式。

绝对 untrue OUTER连接比INNER连接更快(尽管可能有一些查询对此是真的)。因此,根据该理论,尝试将查询转换为使用更多OUTER连接并不是很有用。

有关于性能优化的书籍,但一些一般规则包括

  • 在您的查询中,以最具选择性和最少选择性的顺序执行表连接和WHERE条件(即,如果您有一个将返回集的大小减少80%的连接,则将其放在查询的顶部)。理论上,优化器应该能够根据表统计信息重新排序连接这些标准,但我发现给它提供额外帮助有时会产生差异。

  • 学习阅读SQL执行计划。他们会告诉你完全数据库如何完成你的请求,你可以了解它是否遗漏和索引(或者数据库是否缺少可能对性能有用的索引),当它是能够使用范围,直接索引命中或全表扫描等。

  • 对于运行时间非常长的查询,有时将一些初步结果转移到临时表中,对该表进行适当的索引,然后对该表执行其余的查询。当您需要加入或过滤某些计算标准时会强制对大表进行表扫描时,尤其如此,当您可以找到一些策略来通过更直接的标准预过滤部分结果时

答案 1 :(得分:0)

为了获得最佳效果,请尽快减少您的第一张桌子,以便oracle不会创建大量额外的行来扔掉。然后在子查询中添加该过滤器,而不是在它们完成之后。我试试:

SELECT G.ID, T1.QUANTITY, T2.QUANTITY
  FROM GOODS G
  JOIN DUAL ON G.ID IN (1, 2, 3, 4)
  LEFT JOIN (SELECT SUM(QUANTITY) AS QUANTITY, GOOD_ID
          FROM MY_TABLE_1 T
         GROUP BY GOOD_ID
        ) T1 ON T1.GOOD_ID = G.ID
  LEFT JOIN (SELECT SUM(QUANTITY) AS QUANTITY, GOOD_ID
          FROM MY_TABLE_2 T
         GROUP BY GOOD_ID
        ) T2 ON T2.GOOD_ID = G.ID

答案 2 :(得分:0)

优化工具可以处理大部分事情。 你应该做以下     尝试加入主键     如果不可能,则为连接中涉及的列提供索引     如果可能,使用where子句过滤结果以在连接之前减少源表中的行