通过 BETWEEN 两个值指定的 ON 加速 JOIN

Speed up JOIN with ON specified by BETWEEN two values

令我惊讶的是,用 BETWEEN 子句指定的 ON 连接两个 table 需要这么长时间。在 table A 中,A.KeyUNIQUE,已排序 ascending。在 table B 中,我们有 B.KeyStartB.KeyEnd 列也按升序排序,它们形成排他性区间,如 1-4, 5-6, 7-11 等。

SELECT A.Key, B.Column 
FROM tableA as A 
INNER JOIN  tableB as B
ON A.Key BETWEEN B.KeyStart AND B.KeyEnd

我怎样做才能加快速度?

这主要是比您预期的要慢,因为您希望 DBMS 知道它不知道的事情。

DBMS 不知道不存在重叠范围。因此,从 DBMS 的角度来看,所有 B 记录甚至可能是从最小键到最大键,这意味着将所有 A 记录与所有 B 记录连接起来。只有你知道,一条A记录只有一条B记录。

因此 DBMS 必须通读所有 B 以找出哪些匹配,哪些不匹配。由于没有WHERE子句,所有记录都是相关的,所以使用索引是不可能的。

您可以通过它理解的约束告诉它您所知道的一切来帮助 DBMS:KeyStart 是独一无二的。 KeyEnd 是独一无二的。 (虽然你不能告诉它没有重叠范围。)也许它有帮助,但我实际上怀疑这一点。

此外,您可以创建一个包含所有相关值的索引,因此无需读取 table 本身;将改为读取索引。 Index on tableB(KeyStart, KeyEnd, Column).

一个你可以尝试的想法。如您所知,每个 A 在 B 中只有 one 匹配,因为您知道范围不会重叠,为什么还要看 KeyEnd?它始终是 A 记录的最大 KeyStart B 记录,其中 B.KeyStart 不大于 A.Key。

所以我们得到A,在B中寻找最匹配的StartKey,然后访问整个对应的B记录,以便读取B.Column。您可以在此处使用 SQL 服务器的 CROSS APPLY。

select a.Key, b.Column
from tableA a
cross apply
( 
  select max(KeyStart) as KeyStart from tableB where tableB.KeyStart <= a.Key
) best
join tableB b on b.KeyStart = best.KeyStart;

这可能会更快。这可能会更慢。试试吧。

SQL fiddle: http://www.sqlfiddle.com/#!3/58e44/3.