2

I try to understand how to correct write big queries with a lot of JOIN clause. Are this queries has the same performance?

/*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);

In the next query same WHERE clause set in all joining subqueries and outside LEFT JOIN clause replace on INNER CLAUSE. Is it a good solution? Or oracle optimizer automatic make such things?

/*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);
4

3 回答 3

2

查询性能取决于很多因素,包括:

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

OUTER 连接比 INNER 连接快是绝对不正确的(尽管可能有一些查询是正确的)。因此,尝试将查询转换为使用更多基于该理论的 OUTER 连接并不是很好地利用您的时间。

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

  • 在您的查询中,按照从最高选择性到最低选择性的顺序执行表连接和 WHERE 条件(即,如果您有一个可以将返回集的大小减少 80% 的连接,请将其放在查询顶部附近)。优化器理论上应该能够根据表统计信息对这些条件重新排序,但我发现给它额外的帮助有时会有所作为。

  • 学习阅读 SQL 执行计划。他们将准确地告诉您数据库如何满足您的请求,并且您可以了解它是否丢失和索引(或者数据库是否缺少可能对性能有用的索引),何时能够使用范围,直接索引命中或全表扫描等。

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

于 2013-07-26T06:02:56.030 回答
1

为获得最佳结果,请尽可能快地减少您的第一个表,以免 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
于 2013-07-26T06:02:56.863 回答
0

优化器负责大部分事情。您应该执行以下操作 尝试在主键上连接 如果不可能,则为连接中涉及的列提供索引 如果可能 使用 where 子句过滤结果以在连接前减少源表中的行

于 2013-07-26T06:09:00.363 回答