Gee*_*zer 1 sql-server index-tuning azure-sql-database query-performance
我有一个宽表,相对较大,有 14,264,775 行,在 Azure SQL 数据库上运行。
以下查询需要一些 TLC。
IF EXISTS (
SELECT 1/0
FROM dbo.table1 src
INNER JOIN dbo.table1 tgt
ON tgt.Col1 = src.Col1
WHERE tgt.ValidFrom <= src.ValidTo
AND tgt.ValidTo >= src.ValidFrom
AND tgt.RecordId <> src.RecordId
)
BEGIN
RAISERROR('Overlap detected in dbo.table1', 11, 1);
END ;
Run Code Online (Sandbox Code Playgroud)
我有这个索引。
CREATE NONCLUSTERED INDEX [IX__table1] ON dbo.table1
( Col1 )
INCLUDE (ValidFrom, ValidTo, RecordId)
GO
Run Code Online (Sandbox Code Playgroud)
这是查询的 io 统计信息。逻辑阅读能力非常出色。
这是计划 XML。我尝试了 PasteThePlan,但它无法解析计划 XML。(也许它不喜欢Axure sql数据库计划xml)。
如您所见,[src] 上有一个索引扫描;读取 14,264,775 行(与表中的所有行数相同)。并在 [tgt] 上进行索引查找;读取 194,405,307 行。
我需要改变什么来提高查询的性能?
总共 1400 万行中有 210 万个唯一的 Col1 值。
您似乎手动编辑了 XML 并使其无效,主要是通过添加无效字符(例如<和 )>。修复了一些问题后,我能够将计划加载到 SSMS 和 Plan Explorer 中:
这表明您有一个名为[IX__dbo_table1__DateRange]\xe2\x80\x94 的索引,问题中未提及。从seek谓词来看,该索引在索引键中至少有Col1and 。ValidTo
另一个问题是使用IF EXISTS. 这引入了行目标,这导致优化器倾向于嵌套循环解决方案。请参阅相关的问答IF EXISTS 花费的时间比嵌入的 select 语句更长。
也就是说,找到任何可能的重叠范围是使用 b 树索引完全解决的一个难题,请参阅解决 BETWEEN join - eager spool 的性能问题。
\n如果不知道完整的表定义、索引和数据分布,就很难提出正确的解决方案。如果您只是想要快速轻松地尝试一些东西,而不需要过多更改索引或源查询,请尝试哈希连接提示:
\nIF EXISTS (\n SELECT 1/0 \n FROM dbo.table1 src\n INNER HASH JOIN dbo.table1 tgt -- hint added\n ON tgt.Col1 = src.Col1\n WHERE tgt.ValidFrom <= src.ValidTo\n AND tgt.ValidTo >= src.ValidFrom\n AND tgt.RecordId <> src.RecordId \n)\n BEGIN\n RAISERROR(\'Overlap detected in dbo.table1\', 11, 1); \n END ;\nRun Code Online (Sandbox Code Playgroud)\n这将完全扫描索引两次,但如果您的系统可以处理内存或 I/O 要求,并且并行或批处理模式执行可用,那么这可能还不错。如果有相当数量的不同的,这将是最好的Col1值,这将最有效。
假设应该禁止重叠,我的偏好是首先使用约束来避免这种情况发生。看确保时态数据库设计中唯一条目的正确方法是什么?
\n或者,如ypercube\xe1\xb5\x80\xe1\xb4\xb9聊天中
\nIF EXISTS\n(\n SELECT 1/0\n FROM\n (\n SELECT \n T.ValidFrom,\n PrevValidTo =\n LAG(T.ValidTo) OVER ( \n PARTITION BY T.Col1\n ORDER BY T.ValidFrom)\n FROM dbo.table1 AS T\n ) AS T1\n WHERE \n T1.PrevValidTo >= T1.ValidFrom\n)\nBEGIN\n RAISERROR(\'Overlap detected in dbo.table1\', 11, 1); \nEND;\nRun Code Online (Sandbox Code Playgroud)\n具有如下索引:
\nCREATE NONCLUSTERED INDEX [IX__table1] \nON dbo.table1\n (Col1, ValidFrom) \nINCLUDE \n (ValidTo, RecordId);\nRun Code Online (Sandbox Code Playgroud)\n\n
| 归档时间: |
|
| 查看次数: |
251 次 |
| 最近记录: |