首页 > 解决方案 > 性能 - 选择带有左连接和空值检查的查询

问题描述

我有两个不同的表,分别称为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 表中的空记录。我尝试了一些更改,但无法改进它。

补充说明

任何改进此查询的建议都会非常有帮助。

标签: sqlsql-server

解决方案


好吧,在您的查询中,您需要获取[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此列之一的值。


推荐阅读