我有一个包含 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”格式的数据库引擎能够对其进行优化。
我在这里发现了类似的问题,但答案并不令人满意。
- SQL Server支持上述设置比较语法吗?
不。
- 上述谓词是否等价于集合比较 (A,B,C,D) > (K1,K2,K3,K4)?
是的。
- 鉴于 order by 语句与聚集索引键顺序相匹配,SQL Server 数据库引擎是否足够智能,能够识别该谓词的形式并选择查找具有键(K1、K2、K3、K4)的记录的最佳选项,然后简单地扫描从那里开始下一条记录?或者它将对由 OR 运算符组合的谓词的每个部分执行一系列搜索?
单个 Index Seek 运算符内的独立查找操作。您可能需要仔细编写语句才能获得最优化的结果,具体取决于您的 SQL Server 版本。
参见相关问答:
我还没有做过这个工作,但我认为您正在寻找这个主题的变体 - 为 @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 次 |
最近记录: |