我有以下语句在我的数据中找到明确的名字(~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 超过了任何索引,但我只是想知道这种高成本来自哪里。这两个查询在语义上似乎等同于我。
答案在查询的解释计划中。 它们在语义上可能是等效的,但查询的幕后执行计划却大不相同。
EXISTS 的操作方式与 JOIN 不同,本质上,OR 过滤器语句是将表连接在一起的语句。
第二个查询中不会发生 JOIN,因为您只从一个表中检索记录。
两个查询的结果可能在语义上是等效的,但执行在操作上并不等效。第二个示例从不使用 OR 运算符来组合谓词。第二个示例中的所有谓词都使用 AND 进行组合。
性能更好,因为如果与 AND 组合的第一个谓词的计算结果未为 true,则跳过第二个谓词(或任何其他谓词)(不计算)。如果使用 OR,则必须经常计算两个(或所有)谓词,从而减慢查询速度。(检查 OR 谓词,直到一个谓词的计算结果为 true。
我会考虑测试重写的查询,如下所示...根据"合格"什么被认为是匹配的标准从一个直接加入到另一个...... 然后,在 WHERE 子句中,如果它没有匹配,则将其丢弃
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"创建与不存在相同的结果,给出最终结果。
我将查询恢复为正常的"连接"。