Искреннее спасибо всем.Теперь для меня совершенно очевидно, что это было злоупотребление UNPIVOT.В самом деле, CTE - это просто представления, поэтому они не причинят особого вреда, если вы не используете их ненадлежащим образом.
Итак, основной нашей проблемой было то, что наш сервер (32 ГБ ОЗУ, 8 ЦП, 2 ТБ HDD) был простоне в состоянии управлять большим количеством записей, созданных UNPIVOT.
Допустим, у нас есть HugeTable с полями (F1, F2, F3, F4, F5, F6).RecordCount = 1 000 000 000
Мы используем его следующим образом (псевдокод):
with tmp as (select unpivot HugeTable)
select * from tmp
join ...
where FX is not null
and ...
План запроса оценивает, что наш UNPIVOT создает 6 000 000 000 записей для обработки нашим предложением where.Еще хуже становится то, что в действительности мы объединяем некоторые дополнительные таблицы и выполняем дополнительную фильтрацию.Все это происходит 6 миллиардов раз.Журнал транзакций и база данных tempdb были все еще нетронуты - довольно маленькие.Я не нашел никакой информации о том, что UNPIVOT / JOINS (хеш-соединения, которые нужно прецизировать) использует оперативную память только для управления своими операциями, но из того, что мы поняли, я понимаю, что наш SQL Server 2008 R2 Enterprise просто пытался разместить этот объемный набор записей в оперативной памяти, нопоскольку у нас не было 1 ТБ ОЗУ, операционная система выполняла огромные операции подкачки.
Интересно то, что она может запускаться очень быстро и обрабатывать около 1 800 000 000 записей в течение первых 6 часов, но затем зависает (хорошо, он генерирует 100 тыс. записей в сутки, что совершенно неприемлемо)
Если мы превратим его в руководство UNION ALL, вот так:
with tmp as (
select F1 from HugeTable where F1 is not null
union all select F2 from HugeTable where F2 is not null
union all select F3 from HugeTable where F3 is not null
union all select F4 from HugeTable where F4 is not null
union all select F5 from HugeTable where F5 is not null
union all select F6 from HugeTable where F6 is not null
)
select ... from tmp
join ...
where ...
план запроса показал, что CTE выдал около2 миллиарда записей.Таким образом, все дальнейшие объединения должны были выполняться с гораздо меньшим набором записей, чем в первом случае.На выполнение этой работы ушло менее 10 часов (против дней в первом случае).
Кстати, мы используем среду SSIS / VS2008 для обработки наших загрузок данных.