我们希望将数据从一个表增量加载到另一个表。有重复的机会。实际上它应该很简单,但是随着数据的增加它会变慢。
最简单的部分是直接提取数据。
SELECT s.*
FROM dbo.source_table s
WHERE s.load_datetime > ( SELECT ISNULL(MAX(t.load_datetime) , '0001-01-01')
FROM dbo.target_table AS t
)
查询计划非常快,只识别增量。
如果我想删除重复项,我添加了 DENSE_RANK。
SELECT *
FROM ( SELECT s.*
,DENSE_RANK() OVER ( PARTITION BY s.business_key ORDER BY s.load_datetime ) AS row_no
FROM dbo.source_table s
WHERE s.load_datetime > ( SELECT ISNULL(MAX(t.load_datetime) , '0001-01-01')
FROM dbo.target_table AS t
)
) AS sub
WHERE sub.row_no = 1
问题是,SQL Server 在过滤 load_datetime 之前总是先执行窗口函数。我以各种不同的形式更改了查询并研究了网络以寻求解决方案。我也用 CROSS APPLY 和 CTE 进行了尝试:
WITH data
AS ( SELECT s.*
FROM dbo.source_table s
WHERE s.load_datetime > ( SELECT ISNULL(MAX(t.load_datetime) , '0001-01-01')
FROM dbo.target_table AS t
)
)
SELECT *
FROM ( SELECT *
,DENSE_RANK() OVER ( PARTITION BY business_key ORDER BY load_datetime ) AS row_no
FROM data
) AS sub
WHERE sub.row_no = 1
仍然对 xx mio 行的整个表进行排序,而不是对增量进行排序。
有没有人知道如何在没有窗口函数的情况下只获取子查询的第一行来计算整个数据集?它需要是没有临时表的 SELECT 或 VIEW。
这些是当前计划:brentozar.com/pastetheplan/?id=Sy2IFSjKg(最快,无重复检查)brentozar.com/pastetheplan/?id=BJJpKSstl(对所有 50 行 mio 进行排序)brentozar.com/pastetheplan/?id=Byre5BoFe(与 cte 相同)
我尝试删除列存储索引并创建有用的非聚集索引。没有效果。仍然在 where 子句之前进行密集排序。