Способы избежать нетерпеливых операций спулинга на SQL Server - PullRequest
36 голосов
/ 17 сентября 2008

У меня есть процесс ETL, который включает в себя хранимую процедуру, которая интенсивно использует операторы SELECT INTO (минимально регистрируемые и, следовательно, более быстрые, поскольку они генерируют меньше трафика журнала). Из пакета работ, который выполняется в одной конкретной хранимой процедуре, некоторые из самых дорогих операций - это активные буферы, которые, по-видимому, просто буферизуют результаты запроса и затем копируют их в только что созданную таблицу.

Документация MSDN по нетерпеливым катушкам довольно скудна. Есть ли у кого-нибудь более глубокое понимание того, действительно ли они необходимы (и при каких обстоятельствах)? У меня есть несколько теорий, которые могут иметь или не иметь смысла, но безуспешно в устранении их из запросов.

Файлы .sqlplan довольно велики (160 КБ), поэтому я думаю, что публиковать их непосредственно на форуме, вероятно, нецелесообразно.

Итак, вот несколько теорий, которые могут подстраиваться под конкретные ответы:

  • В запросе используются некоторые пользовательские функции для преобразования данных, например, для анализа форматированных дат. Требует ли это преобразование данных использования активных катушек для выделения разумных типов (например, длины varchar) для таблицы до ее создания?
  • Как продолжение вопроса выше, кто-нибудь имеет более глубокое представление о том, что управляет этой операцией в запросе?

1 Ответ

30 голосов
/ 18 сентября 2008

Мое понимание спулинга заключается в том, что в вашем плане выполнения это немного красной селедки. Да, он учитывает большую часть ваших запросов, но на самом деле это оптимизация, которую SQL Server выполняет автоматически, чтобы избежать дорогостоящего повторного сканирования. Если вы избежите буферизации, стоимость дерева выполнения, на котором оно расположено, возрастет, и почти наверняка стоимость всего запроса увеличится. У меня нет какой-либо конкретной информации о том, что, в частности, может заставить оптимизатор запросов базы данных анализировать выполнение таким образом, особенно без учета кода SQL, но вам, вероятно, лучше доверять его поведению.

Однако это не означает, что ваш план выполнения не может быть оптимизирован, в зависимости от того, что вы делаете, и насколько изменчивы ваши исходные данные. Когда вы делаете SELECT INTO, вы часто видите спулинговые элементы в вашем плане выполнения, и это может быть связано с изоляцией чтения. Если это подходит для вашей конкретной ситуации, вы можете попробовать просто снизить уровень изоляции транзакции до чего-то менее затратного и / или использовать подсказку NOLOCK. В сложных, критичных к производительности запросах я обнаружил, что NOLOCK, если он безопасен и подходит для ваших данных, может значительно увеличить скорость выполнения запроса, даже если нет причин, по которым он должен это делать.

В этой ситуации, если вы попробуете READ UNCOMMITTED или подсказку NOLOCK, вы сможете удалить некоторые из катушек. (Очевидно, что вы не хотите делать это, если это может привести вас в несогласованное состояние, но требования к изоляции данных у всех разные). Оператор TOP и оператор OR могут иногда вызывать спулинг, но я сомневаюсь, что вы выполняете какие-либо из них в процессе ETL ...

Вы правы, говоря, что ваши UDF также могут быть виновником. Если вы используете каждый UDF только один раз, было бы интересно поэкспериментировать с ними, чтобы убедиться, что вы получаете значительное преимущество в производительности. (И если вы не можете найти способ написать их в строке запроса, возможно, именно поэтому они могут вызывать спулинг).

Последнее, на что я хотел бы обратить внимание, - это то, что если вы делаете какие-либо объединения, которые можно переупорядочить, попробуйте использовать подсказку, чтобы заставить порядок объединения произойти в том, что, по вашему мнению, является самым избирательным порядком. Это немного досягаемо, но не помешает попробовать его, если вы уже застряли в процессе оптимизации.

...