Влияние на производительность цепочки CTE против таблицы Temp - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть следующий цепной запрос CTE (упрощенно):

;WITH CTE1
AS(    
    SELECT * FROM TableA
),
CTE2
AS(
    SELECT * FROM TableB b INNER JOIN CTE1 c ON b.id = c.id
)

SELECT * FROM CTE2

Если я разорву цепочку CTE и сохраню данные CTE1 во временной таблице, производительность всего запроса улучшится (с 1 минуты 20 секунд до 8 секунд).

;WITH CTE1
AS(    
    SELECT * FROM TableA
)

SELECT * INTO #Temp FROM CTE1

;WITH CTE2
AS(
    SELECT * FROM TableB b INNER JOIN #Temp c ON b.id = c.id
)

SELECT * FROM CTE2
DROP TABLE #Temp

В CTE1 и CTE2 имеются сложные запросы. Я только что создал упрощенную версию, чтобы объяснить здесь.

Должно ли сломанное кресло CTE улучшить производительность?

Версия SQL Server: 2008 R2

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Считайте, что cte1 стоит дорого

;WITH CTE1
AS(    
    SELECT * FROM TableA
)

SELECT * INTO #Temp FROM CTE1

Над гарантиями cte1 запускается только один раз.

Связанный cte может оценивать cte1 несколько раз.

И даже с #temp вы должны рассмотреть index / PK и отсортировать вставку.

0 голосов
/ 03 ноября 2018

Это зависит от многих факторов. Всегда старайтесь написать единственное утверждение, если можете. Преждевременная оптимизация - корень зла.

Если у вас возникли проблемы с производительностью, вот некоторые из преимуществ разложения вашего единственного утверждения:

  • Это может повысить ремонтопригодность, которая является одним из многих нефункциональных требований, за счет уменьшения сложности.
  • Это может привести к лучшему плану, если стоимость промежуточной материализации и сэкономленное время меньше первоначальной стоимости.
  • Промежуточные таблицы могут быть проиндексированы.
  • Индексы, первичные ключи и уникальные ограничения очень полезны оптимизатору не только для выбора типов соединений, но и для оценки количества элементов, что оказывает большое влияние на предоставление памяти.
  • Можно выбрать применение подсказок оптимизатора, таких как MAXDOP, только для выбора операторов, а не одного гигантского оператора. Это особенно полезно, когда вам нужно манипулировать предоставлением памяти.
  • Вы можете настроить отдельные операторы для устранения разлива в базу данных tempdb.
  • В зависимости от сложности и общего времени выполнения вашего процесса вы можете снять блокировку ресурсов раньше, в зависимости также от того, на каком уровне изоляции работают ваши операторы.
  • Если ваш план запросов плохой, из-за тайм-аута оптимизатора, использование менее сложных отдельных операторов может дать лучшие общие результаты.
0 голосов
/ 02 ноября 2018

Очевидно, что может, как вы сами показали.

Почему? Наиболее очевидная причина заключается в том, что оптимизатор знает размер временной таблицы. Это дает ему больше информации для оптимизации запроса. CTE - только оценка. Итак, улучшение, которое вы видите, связано с планом запросов.

Другая причина может быть в том, что в запросе указывается CTE несколько раз. SQL Server не материализует CTE, поэтому код определения будет выполняться несколько раз.

Иногда вы целенаправленно материализуете CTE как временные таблицы, чтобы в них можно было добавлять индексы. Это также может улучшить производительность.

Все, что сказано, я предпочитаю избегать временных таблиц. Оптимизатор обычно довольно хороший.

...