如何构造谓词以触发具有组合键的特定记录搜索的聚集索引?

Tri*_*nko 10 sql-server

我有一个包含 4 部分复合聚集主键(A、B、C、D)的表,按 A、B、C、D 排序。

我必须通过获取 N 条记录来批量遍历整个表,然后检查的最后一个键(K1、K2、K3、K4)之后的任何值开始获取接下来的 N 条记录。键值不连续。

我正在尝试构造谓词来寻找下一批记录,给定带有复合键(K1,K2,K3,K4)的最后读取记录。

如果 ID 不是复合的,我只需运行一个 select 语句,例如“从表中选择前 N 个,其中 ID > K1”。然而,因为它是一个由 4 部分组成的复合键,所以我必须构造一个特殊的谓词来处理 D 可以小于 K4 的事实,只要 A、B 和 C 中的任何一个或全部大于 K1、K2和K3。

在某些数据库引擎中,我知道可以使用如下设置语法进行此类复合键比较:

where (A,B,C,D) > (K1,K2,K3,K4)

问题1: SQL Server支持上述集合比较语法吗?

如果没有,那么我怀疑我必须像这样构造谓词:

一把钥匙 两把钥匙 三把钥匙 四把钥匙
其中 (A > K1)
按 A 排序
其中 (A = K1 且 B > K2)
OR (A > K1)
按 A、B 排序
其中 (A = K1 且 B = K2 且 C > K3)
OR (A = K1 且 B > K2)
OR (A > K1)
按 A、B、C 排序
其中(A = K1 且 B = K2 且 C = K3 且 D > K4)
OR (A = K1 且 B = K2 且 C > K3)
OR (A = K1 且 B > K2)
OR (A > K1)
A B C D

问题2:上述谓词是否等价于集合比较(A,B,C,D) > (K1,K2,K3,K4)?或者我缺少条件。

问题 3:鉴于 order by 语句与聚集索引键顺序相匹配,SQL Server 数据库引擎是否足够智能,能够识别该谓词的形式并选择查找具有键 (K1、K2、K3、K4) 和的记录的最佳选项然后从那里开始向前扫描下一条记录?或者它会对由 OR 运算符组合的谓词的每个部分执行一系列搜索?我认为其他识别“where (A,B,C,D) > (K1,K2,K3,K4) order by A,B,C,D”格式的数据库引擎能够对其进行优化。

我在这里发现了类似的问题,但答案并不令人满意。

Pau*_*ite 7

  1. SQL Server支持上述设置比较语法吗?

不。

  1. 上述谓词是否等价于集合比较 (A,B,C,D) > (K1,K2,K3,K4)?

是的。

  1. 鉴于 order by 语句与聚集索引键顺序相匹配,SQL Server 数据库引擎是否足够智能,能够识别该谓词的形式并选择查找具有键(K1、K2、K3、K4)的记录的最佳选项,然后简单地扫描从那里开始下一条记录?或者它将对由 OR 运算符组合的谓词的每个部分执行一系列搜索?

单个 Index Seek 运算符内的独立查找操作。您可能需要仔细编写语句才能获得最优化的结果,具体取决于您的 SQL Server 版本。

参见相关问答:


sqL*_*dLe 1

我还没有做过这个工作,但我认为您正在寻找这个主题的变体 - 为 @lasta、@lastb、@lastc 和 @lastd 提供适当的数据类型以及适当的起始值。

DECLARE @lasta VARCHAR(5) = '', @lastb VARCHAR(5) = '', @lastc VARCHAR(5) = '', @lastd VARCHAR(5) = '';
DECLARE @N INT = 100000;

WHILE EXISTS
  (SELECT TOP (1) t.a, t.b, t.c, t.d
   FROM table t
   WHERE
     (t.a > @lasta)
   OR
     (t.a = @lasta
      AND t.b > @lastb)
   OR
     (t.a = @lasta
      AND t.b = @lastb
      AND t.c > @lastc)
   OR
     (t.a = @lasta
      AND t.b = @lastb
      AND t.c = @lastc
      AND t.d > @lastd)
   ORDER BY t.a ASC, t.b ASC, t.c ASC, t.d ASC)

   BEGIN

      SELECT TOP (N) t.a, t.b, t.c, t.d
      INTO #temp
      FROM table t
      WHERE
        (t.a > @lasta)
      OR
        (t.a = @lasta
         AND t.b > @lastb)
      OR
        (t.a = @lasta
         AND t.b = @lastb
         AND t.c > @lastc)
      OR
        (t.a = @lasta
        AND t.b = @lastb
        AND t.c = @lastc
        AND t.d > @lastd)
      ORDER BY t.a ASC, t.b ASC, t.c ASC, t.d ASC;

      SELECT TOP (1) @lasta = t.a, @lastb = t.b, @lastc = t.c, @lastd = t.d
      FROM #temp
      ORDER BY t.a DESC, t.b DESC, t.c DESC, t.d DESC;

      DROP TABLE #temp IF EXISTS;

   END
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

626 次

最近记录:

2 年,8 月 前