我试着理解如何使用大量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);
答案 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子句过滤结果以在连接之前减少源表中的行