【问题标题】:Oracle SQL Slow JoinOracle SQL 慢连接
【发布时间】:2018-01-06 12:00:06
【问题描述】:

我一直在处理一个运行缓慢的查询,类似于以下内容

select
    count(*)
from
    a
    join b
        on a.akey = b.akey
    join c 
        on b.bkey = c.bkey
    left join d
        on c.ykey = d.ykey
        and b.xkey = d.xkey
where
    a.idkey = 'someid'

这个查询需要 130 秒才能运行 'someid'

如果我删除左连接的任一条件,查询将在

我已确定此特定记录 (someid) 的问题。有大量匹配的 d.xkey 值(~5 000 000)。我已经进行了一些测试,并将此记录的相关 d.xkey 值修改为更多唯一值,从而将运行时间缩短到

这是我目前正在使用的修复程序。

select
    count(*)
from
    a
    join b
        on a.akey = b.akey
    join c 
        on b.bkey = c.bkey
    left join d
        on c.ykey = d.ykey
where
    a.idkey = 'someid'
    and (
        b.xkey = d.xkey
        OR b.xkey is null
        OR not exists (
            select
                dd.xkey
            from
                d dd
            where
                dd.xkey = b.xkey
                and dd.ykey = c.ykey
        )
    )

此查询运行时间不到 1 秒。

我的问题是,为什么这比左连接快这么多?

就结果而言,我的新查询是否与旧查询相同?

【问题讨论】:

标签: sql oracle


【解决方案1】:

如果连接到db.xkeyc.ykey 单独有效(这些名称非常微妙),但当两者结合时就不行,这可能是因为它能够在@987654324 上使用索引@ 为每个单独的,但没有可用的组合索引。

您发布的带有NOT EXISTS 子句的第二个示例几乎是深不可测的,但至关重要的是,它包含额外的逻辑,并且不直接等同于第一个示例中的LEFT JOIN

在第二个示例的WHERE 子句中,您允许包含在cd 之间左连接的行,其中b.xkeynull,而在第一个示例中,这些行的连接永远不会发生(因为b.xkeynull 会排除左连接)。这意味着 d 可能已经不正确地乘以结果集中的行,这些行不能被 where 子句过滤(因为没有 ROW_NUMBER 函数,where 子句无法区分每个不正确的匹配 - 并且只能过滤所有或者都没有,而不是将它们缩减为单行),因此仅在这一点上,这两个查询就可以被认为在逻辑上并不相同。

否则很难准确推断整个 where 子句的组合效果是什么,以及它如何与其他约束和基础数据交互以使查询更好地执行(尽管表面上必须执行与第一个示例中的左连接类似的查找)。如果您从两个查询中得到相同的结果,我会说这只是因为数据中存在危险的巧合,而两个查询施加的逻辑约束根本不同。

【讨论】:

  • 你是对的,组合键上没有创建索引。
  • @Jamie,很高兴你把它整理好了。不要忘记标记为已回答! :)
【解决方案2】:

这两个查询在逻辑上似乎并不相等。有条件就可以理解了

OR b.xkey 为 null 。 a=b 和 b=c 和 c=d(+)

如果您采用 OR b.xkey 为 null 则 a=b 正在过滤掉一些数据。 实际上两者有很大不同。

【讨论】:

    猜你喜欢
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2016-10-02
    • 2012-05-13
    相关资源
    最近更新 更多