旧系统已经到我们办公室进行一些更改和修复,但它也遇到了性能问题。我们不确切知道这种缓慢的根源是什么。
当我们重构旧代码时,我们发现了几个带有以下模式的SQL查询(查询被简化为例如目的):
SELECT
(
SELECT X
FROM A
WHERE A.id = TABLE.id
) AS COLUMN1,
(
SELECT Y
FROM B
WHERE B.id = TABLE.id
) AS COLUMN1,
(
SELECT Z
FROM C
WHERE C.id = TABLE.id
) AS COLUMN1,
...
FROM
TABLE
WHERE
TABLE.id = @param;
这些查询会从他们返回的每个列中执行几个内部子查询。
我们计划在以下模式中重写这些查询:
SELECT
A.X, B.Y, C.Z
FROM
TABLE
INNER JOIN A on A.ID = TABLE.ID
INNER JOIN B on B.ID = TABLE.ID
INNER JOIN C on C.ID = TABLE.ID
WHERE
TABLE.id = @param;
通过内部联接,更容易阅读和理解,但它真的更快吗?这是写它们的更好方法吗? 不幸的是,我们重写的第一个没有改善查询时间,它使查询有点慢。
这是我的问题:我们应该重写所有这些查询吗?这些子查询是否是完成这项工作的好方法?他们加快了内联方式吗?
答案 0 :(得分:15)
如果我正确理解了您的问题,那么您正在开始重写某些SQL语句的操作,因为您认为它们可能存在问题。
我的建议是停下来,先开始确定你的时间目前在哪里。 只有在您发现它与那些标量子选择的查询中之后,并且由于这些标量子选择,您才应该重写它们。 在那之前:开始追踪和检查。
以下是来自OTN的两个主题,用于指导有性能问题的人:
http://forums.oracle.com/forums/thread.jspa?messageID=1812597 http://forums.oracle.com/forums/thread.jspa?threadID=863295
的问候,
罗布。
并且:由于scalar subquery caching,您的原始查询可能比使用连接的重写查询快得多。
答案 1 :(得分:8)
子查询实际上每行都运行一次,而联接则发生在索引上。
使用联接可以提高可读性和可维护性,正如您在问题中已经提到的那样。
答案 2 :(得分:4)
联接将为您提供更好的性能,但我建议您在“优化”查询时查看执行计划。
答案 3 :(得分:2)
作为this answer argues,应不会影响性能。但是,某些查询优化器可能在JOIN上表现更好,因此您应该在系统上进行一些实验。
现在,对于完全不同的内容:JOIN
每个表格到下一个表格可能比使用JOIN
TABLE
更加美观,并且每当id出现时都会出现错误曾经在其中一个表格中:
SELECT
A.X, B.Y, C.Z
FROM
TABLE
INNER JOIN A on A.ID = TABLE.ID
INNER JOIN B on A.ID = B.ID
INNER JOIN C on B.ID = C.ID
WHERE
TABLE.id = @param;
答案 4 :(得分:0)
这里内部连接更好。原因如下:
1-在主查询中,您正在引用/使用子查询中使用的表中的值。加入就是为了这个目的。您的要求是-“通过连接不同的表来获取一些值,因为无法从一个表中获得这些值”。
当主查询中未引用子查询的列时,应使用子查询。 喜欢:
select * from emp where deptno in ( select deptno from dept );
在这里,您在问-“请给我所有在部门编号 deptno 工作的员工”。您对此部门的 deptno 不太担心。
2-您已经提到过另一个原因是可读性。
3-在性能方面,您不必担心,因为优化器知道该怎么做。
有关更多详细信息,请检查here。