问题:
我能以某种方式提示SQL Server从索引搜索返回的预期行数吗?
背景:
我有一个唯一的聚集索引:
ALTER TABLE [dbo].[T] ADD CONSTRAINT [X] PRIMARY KEY CLUSTERED
(
[Int1] ASC,
[Int2] ASC,
[Int3] ASC,
[Int4] ASC
)
SELECT
...
FROM [dbo].[T]
WHERE
[Int1] = @Int1 AND
[Int2] = @Int2 AND
[Int3] = @Int3 AND
[Int4] = @Int4
这是即时运行的。具有参数@Int1-4的任何值
如果我用循环迭代@Int4的值递增(是的,这在SQL中听起来完全是错误的),我会立即得到结果。
-- Looks completely wrong for SQL - but it seems to be fastest way to fetch range of values
DECLARE @I INT = 1
WHILE @I <= 50
BEGIN
SELECT
...
FROM [dbo].[T]
WHERE
[Int1] = @Int1 AND
[Int2] = @Int2 AND
[Int3] = @Int3 AND
[Int4] = @I
SET @I = @I + 1
END
GO
如果我将最后一个条件指定为范围:
SELECT
...
FROM [dbo].[T]
WHERE
[Int1] = @Int1 AND
[Int2] = @Int2 AND
[Int3] = @Int3 AND
[Int4] BETWEEN @Int4 AND (@Int4 + 2)
如果我完全忽略了[Int4]约束,也会发生同样的情况。
不同之处在于返回的估计行与实际行数。在精确的情况下,两者都是1。如果是“介于”或“省略”的情况,则差别很大:
有什么方法可以让between或省略条件更快地运行?有什么方法可以提示SQL行数将非常低吗?
顺便说一句,这个表包含730亿行。数据大小约为1.7TB,索引大小约为4.2TB。
它可能需要重建,但是需要大量的停机时间。另外,如果我只切换到dummy cycle,我可以快速简化查询。
按要求-这是表和索引的实际DDL(前4列是我上面简化的示例中的INT1-INT4):
CREATE TABLE [dbo].[RelationalResultValueVectorial](
[RelationalResultRowId] [bigint] NOT NULL,
[RelationalResultPropertyId] [int] NOT NULL,
[RelationalResultVectorialDimensionId] [int] NOT NULL,
[OrdinalRowIdWithinProperty] [int] NOT NULL,
[RelationalResultValueId] [bigint] IDENTITY(1,1) NOT NULL,
CONSTRAINT [Idx_RelationalResultValueVectorial] PRIMARY KEY CLUSTERED
(
[RelationalResultRowId] ASC,
[RelationalResultPropertyId] ASC,
[RelationalResultVectorialDimensionId] ASC,
[OrdinalRowIdWithinProperty] ASC
) ON [RelationalDataFileGroup]
) ON [RelationalDataFileGroup]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_RelationalResultValueVectorial_ValueId] ON [dbo].[RelationalResultValueVectorial]
(
[RelationalResultValueId] ASC
) ON [RelationalDataFileGroup]
GO
-- + some FKs
关于参数嗅探的答案-这里是如果我只使用常量(仍然是错误的估计和仍然非常缓慢的执行)得到的结果: