sql – Oracle更快的重叠检查

我有一个包含两列beginrange和endrange的表.不应该允许重叠范围.这些列上有索引,我们尝试过很多sql条件,比如

inputBegin between beginRange and endRange or
inputEnd between beginRange and endRange 

不(inputEnd< beginRange或inputStart> endRange)

等等
哪个工作正常,除非它们非常慢,因为表包含超过5mil的记录.

反正有没有写一个高效的重叠检查?

编辑:
我想到了另外一个解决方案,只有当count()在带有索引的NOT NULL列上完成时,oracle才会计算索引.如果beginRange和endRange是NOT NULL并且两者都有索引,我们可以有三个总和:

count(endRange) where inputBegin > endRange
+
count(beginRange) where inputEnd < beginRange
=
count(beginRange/endRange)

因此,对于UNION ALL,我会得到三行,在代码中我需要检查前两个的总和是否等于第三个.当然我假设只计算索引,不会访问任何行.还有其他方法吗?

最佳答案 我不确定你是否愿意:

>检查您要插入的行是否与某些现有行重叠,或者
>搜索所有现有行并识别重叠的行?

如果(1),那么你基本上已经在做什么了……

SELECT *
FROM YOUR_TABLE
WHERE :inputEnd > beginRange AND :inputStart < endRange;

…会给你重叠并且应该非常高效,前提是你有一个复合索引,其组件方向相反:{beginRange ASC,endRange DESC}.

如果(2),那么你可以像这样使用窗口:

SELECT *
FROM (
    SELECT
        YOUR_TABLE.*,
        LEAD(beginRange) OVER (ORDER BY beginRange) nextBeginRange
    FROM YOUR_TABLE
)
WHERE endRange > nextBeginRange;

这将为您提供与其下一个范围重叠的每个范围(其中“next”的含义在beginRange排序的上下文中定义).

严格来说,这甚至不需要复合索引(除非你想要covering) – 只需{beginRange}上的一个简单索引即可确保良好的性能.

点赞