【问题标题】:What is better? Subqueries or inner joining ten tables?什么是更好的?子查询还是内部连接十张表?
【发布时间】:2011-06-22 17:11:06
【问题描述】:

一个旧系统已运抵我们的办公室进行一些更改和修复,但它也存在性能问题。我们不知道这种缓慢的确切原因是什么。

当我们重构旧代码时,我们发现了几个具有以下模式的 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;

使用内部连接,它们更易于阅读和理解,但它真的更快吗?这是写它们的更好方法吗? 不幸的是,我们重写的第一个并没有缩短查询时间,反而使查询速度变慢了一些。

这是我的问题:我们应该重写所有这些查询吗?这些子查询是完成这项工作的好方法吗?它们是否比内部连接方式更快?

【问题讨论】:

标签: sql oracle select


【解决方案1】:

子查询实际上对每一行运行一次,而连接发生在索引上。

正如您在问题中已经提到的那样,使用连接以获得更好的可读性和可维护性。

【讨论】:

  • 为什么?如果有索引,应该申请简单的id搜索。
  • 有时表没有通过它们的索引列连接。是否会影响对内连接的偏好?
  • @Adam,@Gustavo - 性能取决于您运行查询的数据库引擎。您必须使用执行计划检查性能(不确定它在 oracle 中的确切名称)。有时子查询更好,有时连接更好,但最终为了更好的可读性和维护查询,连接有一点优势。
  • 由于标量子查询缓存,这个答案并不总是正确的。
【解决方案2】:

联接将为您提供更好的性能,但我建议在“优化”查询时查看执行计划。

【讨论】:

  • 我应该留意计划,谢谢。没有测量结果就没有真正的调整。
【解决方案3】:

作为this answer argues,它应该不会影响性能。但是,某些查询优化器可能在 JOIN 上表现更好,因此您应该在您的系统上进行一些实验。

现在换一种完全不同的方式:JOIN将每个表转到下一个可能比 JOINing 全部使用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;

【讨论】:

  • 谢谢你的例子。当然,最好阅读。在我的示例中,只有 3 个连接,但这里的每个查询每次查询执行 10 次或更多次...
【解决方案4】:

如果我正确理解了您的问题,您将开始一项操作来重写您的一些 SQL 语句,因为您认为它们可能存在问题。

我的建议是停止并首先确定您当前的时间都花在了哪里。 只有在您发现它在带有这些标量子选择的查询中并且是因为这些标量子选择之后,您才应该重写它们。 在那之前:开始追踪和检查。

以下是来自 OTN 的两个线程,用于指导有性能问题的人:

http://forums.oracle.com/forums/thread.jspa?messageID=1812597 http://forums.oracle.com/forums/thread.jspa?threadID=863295

问候,
抢。

并且:由于scalar subquery caching,您的原始查询可能比使用连接重写的查询快很多。

【讨论】:

  • 你的回答告诉了我一些我不知道的事情:“标量子查询缓存”。也许子查询有时会很好。但是,我们重写了另一个查询并得到了更好的结果,从 0.5s 到 0.04s。我将您的帖子签署为正确的帖子,因为对于某些人来说,子查询可能确实是一个很好的解决方案。谢谢。
【解决方案5】:

这里内部连接更好。原因如下:

1- 在您的主查询中,您正在引用/使用子查询中使用的表中的值。加入就是为此而生的。您的问题是 - “通过加入不同的表格来获取一些值,因为这些值无法从一张表格中获得”。

当主查询中未引用子查询中的列时,应使用子查询。 喜欢:

select * from emp where deptno in ( select deptno from dept ); 

你在这里问-“给我所有在部门编号 deptno 工作的员工”。你不太关心这个deptno in dept。

2- 另一个原因是您已经提到的可读性。

3- 在性能方面您不必担心,因为优化器知道该怎么做。

更多详情,请查看here

【讨论】:

    猜你喜欢
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2018-04-09
    相关资源
    最近更新 更多