提问人:SoItBegins 提问时间:10/28/2023 最后编辑:SoItBegins 更新时间:10/28/2023 访问量:48
筛选索引上的最大键长度警告,但由于筛选器,实际键总是更小 - 这安全吗?
Maximum key length warning on a filtered index, but the actual key will always be smaller because of the filter - is this safe?
问:
我正在优化 SQL Server 2019 中的查询。这是一个非常大的表的数据查找,涉及返回大量数据,因此我正在为它创建一个自定义索引。
以下是索引:
CREATE UNIQUE NONCLUSTERED INDEX UQ_DataValues_FilteredEndVSNullDesc2
ON [dbo].[DataValues] (
[EndTime] ASC,
[ValueString] ASC,
[DomainId] ASC,
[FieldType] ASC,
[StartTime] DESC
)
INCLUDE ([Id],[ValueNumber])
WHERE ([EndTime] IS NULL AND [ValueString] IS NULL);
数据库表中的每一行都必须具有 ValueNumber () 或 ValueString () 之一。另一个值将为 NULL。每行还必须有一个 StartTime (),并且可能有一个 EndTime(也是)。如果某行没有 EndTime,则它将为 NULL。float
nvarchar(4000)
datetimeoffset(7)
datetimeoffset(7)
对于此特定查询,我知道我正在查找的数据将设置 ValueNumber 和 ValueString NULL。我也知道它是一种没有 EndTime 的类型——因此是索引过滤器。
我遇到的问题是,当我创建索引时,MSSQL警告:
Warning! The maximum key length for a nonclustered index is 1700 bytes. The index 'UQ_DataValues_FilteredEndVSNull' has maximum length of 8028 bytes. For some combination of large values, the insert/update operation will fail.
好吧,我确实将 ValueString 放在索引键中。但:
- 由于过滤器,我知道 ValueString 将始终为 NULL。
- 如果我没有将 ValueString(或 EndTime)放在键中,则查询优化器将在我执行查找时对其进行聚簇索引扫描,即使它与索引的筛选器谓词完全匹配(即使我使用索引提示)。这效率要低得多。
我的问题是:这安全吗?具有 ValueString 的数据将被添加到表中,但不会添加到索引中,因此此特定键公式实际上不会导致任何插入/更新失败 - 是吗?
编辑:我被要求包含示例查询。这是它大致的样子。实体框架将在实际查找中生成查询,但它是这样的:
SELECT TOP (5000000)
[Project1].[Id] AS [Id],
[Project1].[FieldType] AS [FieldType],
[Project1].[StartTime] AS [StartTime],
[Project1].[ValueNumber] AS [ValueNumber],
[Project1].[DomainId] AS [DomainId]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[DomainId] AS [DomainId],
[Extent1].[FieldType] AS [FieldType],
[Extent1].[StartTime] AS [StartTime],
[Extent1].[ValueNumber] AS [ValueNumber]
FROM [dbo].[DataValues] AS [Extent1] --WITH (INDEX(UQ_DataValues_FilteredEndVSNullDesc2)) , ideally
WHERE ([Extent1].[EndTime] IS NULL) AND
([Extent1].[ValueString] IS NULL) AND
([Extent1].[StartTime] >= '01/01/2023') AND
([Extent1].[StartTime] <= '10/26/2023') AND
([Extent1].[DomainId] IN (1000003592, 1000003594, 1000003596, 1000003595, 1000004919, 1000004922, 1000004920, 1000004921, 1000003565, 1000003564, 1000003563, 1000003562, 1000004876, 1000004877, 1000004878, 1000004879, 1000003517, 1000003516, 1000003519, 1000003518, 1000003822, 1000003823, 1000003824, 1000003825, 1000003962, 1000003968, 1000003967, 1000003970)) AND
([Extent1].[FieldType] IN (1))
) AS [Project1]
ORDER BY [Project1].[Start] DESC
对于现有索引(不是上面显示的索引),此查询需要 1 分钟,该索引不包括 ValueNumber 或 ValueString。当我使用上面显示的索引时,在键中包括 ValueString 和 EndTime,时间下降到 50 秒。如果我不在键中包含 ValueString 和 EndTime,则与现有索引相比,我没有任何好处。
请注意,该查询是实际查询的玩具版本,使用现有索引需要 10 分钟 (!)。我想尽快得到它。
答: 暂无答案
评论