sql - 性能 - 选择带有左连接和空值检查的查询
问题描述
我有两个不同的表,分别称为Processing (30M records for now)
和EtlRecord (4.3M records for now)
。正如表的名称所暗示的,这些表将用于使用 ETL 对数据进行规范化。
我们正在尝试处理批次记录,其中每批次有 1000 条记录。
SELECT TOP 1000 P.StreamGuid
FROM [staging].[Processing] P (NOLOCK)
LEFT JOIN [core].[EtlRecord] E (NOLOCK) ON E.StreamGuid = P.StreamGuid
WHERE E.StreamGuid IS NULL
AND P.CompleteDate IS NOT NULL
AND P.StreamGuid IS NOT NULL
现在执行此查询大约需要 20 秒。我们期待有越来越多的数据,尤其是在 EtlRecord 表中。为了能够提高此查询的性能,我检查了我在下面共享的实际执行计划。
如您所见,最耗时的部分是索引查找以确定 EtlRecord 表中的空记录。我尝试了一些更改,但无法改进它。
补充说明
- 执行计划的所有建议索引已应用于表。所以没有进一步的索引建议。
- 表中有 8 列,
Processing
主要是布尔标志,表中有 4 列EtlRecord
。 - EtlRecord 表仅由单个过程使用。所以事务锁没有问题。
任何改进此查询的建议都会非常有帮助。
解决方案
好吧,在您的查询中,您需要获取[staging].[Processing]
在[core].[EtlRecord]
.
您可以先删除已处理的记录。
DELETE [staging].[Processing]
FROM [staging].[Processing] P
INNER JOIN [core].[EtlRecord] E
ON E.StreamGuid = P.StreamGuid;
如果需要,您可以批量使用删除。删除这些记录将简化我们的初始查询和讨厌的连接 by uniqueidentifier
。您只需要为每个批次执行以下操作:
SELECT TOP 1000 StreamGuid
INTO #buffer
FROM [staging].[Processing]
WHERE CompleteDate IS NOT NULL
AND StreamGuid IS NOT NULL;
-- do whatevery you need with this records
DELETE FROM [staging].[Processing]
WHERE StreamGuid IN (SELECT StreamGuid FROM #buffer);
此外,您说过您创建了所有索引,但执行计划建议的索引并不总是最好的。这部分在这里:
WHERE CompleteDate IS NOT NULL
AND StreamGuid IS NOT NULL;
似乎非常适合过滤索引,特别是如果大量行具有NULL
此列之一的值。
推荐阅读
- python - 解析XML:Python ElementTree,查找元素及其父元素,而不是同一父元素中的其他元素
- python - Python中的Vigenere密码不适用于大写/小写字母转换
- java - 在另一个 @Configuration 类中使用 @Configuration Bean 的最佳实践
- r - 字符串中的第一个数字用“*”分隔字符串
- google-colaboratory - 我们如何将存储库从 Google Colaboratory 推送到 Github
- python-3.x - 如何仅使用 while 循环来实现以下功能?
- django - 如何在 django 应用程序中动态显示消息?
- java - 许多长任务上的 ScheduledExecutorService
- python - 无法移动 URL 以在 Django 中导入 URL
- dataweave - (Dataweave 1.0)转换后的消息包括命名空间(不应该)