7

我有以下语句可以在我的数据中找到明确的名称(约 100 万个条目):

select Prename, Surname from person p1 
where Prename is not null and Surname is not null 
and not exists (
   select * from person p2 where (p1.Surname = p2.Surname OR p1.Surname = p2.Altname) 
   and p2.Prename LIKE CONCAT(CONCAT('%', p1.Prename), '%') and p2.id <> p1.id
) and inv_date IS NULL

Oracle 显示 1477315000 的巨大成本,并且执行在 5 分钟后没有结束。只需将 OR 拆分为一个自己的存在子条款即可将性能提高到 0.5 秒,并将成本提高到 45000:

select Prename, Surname from person p1 
where Prename is not null and Surname is not null 
and not exists (
   select * from person p2 where p1.Surname = p2.Surname and
   p2.Prename LIKE CONCAT(CONCAT('%', p1.Prename), '%') and p2.id <> p1.id
) and not exists (
   select * from person p2 where p1.Surname = p2.Altname and 
   p2.Prename LIKE CONCAT(CONCAT('%', p1.Prename), '%') and p2.id <> p1.id
) and inv_date IS NULL

把它调整到最好不是我的问题,因为它只是一个很少执行的查询,而且我知道 CONTACT 超过了任何索引,但我只是想知道这么高的成本是从哪里来的。这两个查询在语义上似乎与我等效。

4

3 回答 3

6

答案在 EXPLAIN PLAN 中供您查询。它们在语义上可能是等效的,但查询的幕后执行计划却大不相同。

EXISTS 与 JOIN 的操作方式不同,本质上,您的 OR 过滤器语句将表连接在一起。

第二个查询中没有 JOIN 发生,因为您只从一个表中检索记录。

于 2011-05-23T14:38:37.230 回答
2

您的两个查询的结果可能在语义上是等效的,但执行在操作上并不等效。您的第二个示例从不使用 OR 运算符来组合谓词。第二个示例中的所有谓词都使用 AND 组合。

性能更好,因为如果与 AND 组合的第一个谓词未评估为真,则跳过第二个(或任何其他谓词)(未评估)。如果您使用 OR,则必须经常评估两个(或所有)谓词,从而减慢查询速度。(ORed 谓词被检查,直到一个评估为真。)

于 2011-05-23T14:42:41.873 回答
1

我会考虑测试重写如下的查询......根据“限定”什么被认为是匹配的标准从一个直接连接到另一个......然后,在 WHERE 子句中,如果它没有,则将其丢弃t 想出一场比赛

select 
      p1.Prename, 
      p1.Surname
   from 
      person p1 
         join person p2
            on p1.ID <> p2.ID
            and (  p1.Surname = p2.Surname
                or p1.SurName = p2.AltName )
            and p2.PreName like concat( concat( '%', p1.Prename ), '%' )
   where
          p1.PreName is not null
      and p1.SurName is not null
      and p1.Inv_date is null
      and p2.id is null

根据您的评论,但从您正在寻找的内容来看...不,不要进行左外连接...如果您正在寻找与您想要清除的名称相似的名称(但是您会处理),您只想通过自联接(因此正常联接)对那些确实匹配的记录进行预审。如果您的名称没有相似的名称,您可能希望不理会它......因此它将自动被排除在结果集中之外。

现在,WHERE 子句开始了......左边有一个有效的人......右边有一个人......这些是重复的......所以你有匹配,现在通过输入逻辑“ p2.ID IS NULL" 创建与 NOT EXIST 相同的结果,给出最终结果。

我将查询恢复为正常的“加入”。

于 2011-05-23T14:53:45.473 回答