【问题标题】:How good is it to write a query like this?编写这样的查询有多好?
【发布时间】:2017-03-24 11:22:04
【问题描述】:
select 
a,
b,
(select x from table3 where id = z.id) as c,
d
from 
table1 z, table2 zz
where z.id = zz.id;

我知道查询可以很容易地简化如下:

select a,
b,
c.x,
d
from
table1 z,table2 zz, table3 c,
where z.id = zz.id and z.id = c.id;

但我想知道 case1 中的性能影响或额外执行是什么,或者它们都具有相同的性能?只求知识。

【问题讨论】:

  • 没有可比性。如果 table3 没有匹配,第一个查询将返回该列的 null,而第二个查询将不返回任何行。
  • 今日提示:切换到现代、明确的JOIN 语法!更容易编写(没有错误),更容易阅读维护,如果需要更容易转换为外连接!
  • @jarlh 我假设在有数据时进行比较。好吧,我知道编写这样的查询不是一个好习惯,但我正在研究使用这种编码风格的遗留代码。
  • 好吧,如果它已经工作多年了,请不要碰它!
  • 如果您使用标量子查询(如在您的第一条语句中),Oracle 将缓存结果。这意味着,如果您的不同 z.id 值数量相对较少,则可能会带来性能优势,因为它只需为每个不同的值运行一次子查询。

标签: sql database oracle query-performance


【解决方案1】:

如果您想使用相关子查询(这很好),那么您应该这样做:

select a, b,
       (select t3.x from table3 t3 where t3.id = z.id) as c,
       d
from table1 z join
     table2 zz
     on z.id = zz.id;

重要变化:

  • 限定所有列名(我不知道abd 来自哪里)。
  • 使用显式join

你也可以把这个查询写成:

select a, b, t3.x, d
from table1 z join
     table2 zz
     on z.id = zz.id left join
     table3 t3
     on t3.id = z.id;

此查询与上一个查询略有不同。如果子查询返回多行,前一个将返回错误。这会将每个这样的值放在不同的列中。

也就是说,Oracle 优化器相当不错。如果有任何明显的性能差异,我会感到惊讶。

【讨论】:

    【解决方案2】:

    带有关联子查询的第一个查询将始终返回数据,即使 table3 为空。您需要外连接才能获得相同的结果:

    select a,
           b,
           c.x,
           d
    from table1 z
    join table2 zz on z.id = zz.id
    left join table3 c on z.id = c.id
    

    【讨论】:

      【解决方案3】:

      使用 join 查询更具可读性

      但性能是一样的

      select a,
      b,
      c.x,
      d
      from table1 z
      join table2 zz on z.id = zz.id
      join table3 c on z.id = c.id;
      

      【讨论】:

      • the performance is the same - 但这不一定是真的。 Oracle 可以并且将进行标量子查询缓存,因此如果不同 z.id 值的数量相对较少,Oracle 可以为每个不同的 z.id 值运行一次标量子查询,并在其他地方遇到该值时重用它。跨度>
      【解决方案4】:

      如果您的子查询基于单个输入返回单个值,则它是标量子查询。标量子查询可能会提高查询的性能。它将在几个基本条件下这样做。首先,如果 z.id 的可能值数量相对较少。如果我记得的话,标量子查询处理将缓存多达 254 个值。其次,如果查询的其余部分返回相对较多的行数。在这种情况下,如果您只返回几行,那么缓存将没有机会提供帮助。但是如果你要返回很多行,缓存的好处就会增加。

      其他人已经强调了您的原始查询不完全相同。

      在此处查看有关标量子查询的更多信息 -> Scalar Subqueries

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多