Оконная функция SQL Server с условиями (условие where для инкрементальной загрузки)
Мы хотели бы постепенно загружать данные из одной таблицы в другую. Есть вероятность наличия дубликатов. На самом деле это должно быть очень просто, но с увеличением данных становится медленнее.
Самая простая часть - извлечь данные напрямую.
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
Тем не менее сортировка всей таблицы хх строк Mio вместо дельты.
У кого-нибудь есть идея, как получить только первую строку подзапроса без оконной функции для расчета всего набора данных? Это должен быть SELECT или VIEW без временной таблицы.
Это текущие планы: http://brentozar.com/pastetheplan/?id=Sy2IFSjKg (самая быстрая, без повторной проверки) http://brentozar.com/pastetheplan/?id=BJJpKSstl(сортировка всех 50 миллионов строк) http://brentozar.com/pastetheplan/?id=Byre5BoFe (cte же)
Я попытался удалить индекс хранилища столбцов и создать полезные некластеризованные индексы. Нет эффекта. Все еще делает плотный ранг перед предложением where.