ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ Стиль против производительности

Должен ли я использовать отдельный CROSS APPLY для каждого выражения с псевдонимом или определить несколько выражений в одном и том же CROSS APPLY, где это возможно?

Я рефакторинг многих очень сложных SQL-запросов (часто четыре или пять страниц длиной с дюжиной JOIN), которые генерируются в коде. Часто они вложены в пять или шесть запросов вглубь, так как некоторые части повторно используются в разных ситуациях. Типичная причина вложения запросов заключается в том, что один запрос извлекает некоторые значения, выполняет вычисления и присваивает псевдоним значению. Затем объемлющий запрос выполняет дальнейшие вычисления с использованием значения с псевдонимом и т. д. Это необходимо, поскольку на выражение с псевдонимом можно ссылаться только во внешнем запросе, а не где-либо еще в запросе, который его определяет. (Альтернатива, которая также присутствует в коде, состоит в том, чтобы повторять одно и то же длинное подвыражение десятки раз на протяжении всего запроса.)

Чтобы упростить этот спагетти-SQL, я начал сворачивать эти телескопические запросы с помощью CROSS APPLY. Используя CROSS APPLY, я могу назначить псевдоним и использовать его в другом месте того же запроса. Обратите внимание, что ни одно из моих предложений CROSS APPLY не вводит новые таблицы через подзапросы и не вызывает UDF.

Сначала я вложил много выражений в один и тот же CROSS APPLY. Однако мой код должен быть модульным. В разных ситуациях понадобятся разные поля, так как пользователи могут выбирать поля для фильтров, а мы генерируем одинаковую статистику для разных столбцов, следовательно, создаем много похожих запросов, мало отличающихся друг от друга. Поскольку некоторые поля основаны на других, а некоторые зависят от определенных JOIN, определенных ранее в запросе, я не могу поместить все в один и тот же CROSS APPLY. Следовательно, количество CROSS APPLY может варьироваться.

Кроме того, некоторые поля, которые извлекаются из, затеняются новыми псевдонимами и переопределяются (обычно для удаления значений NULL, предоставления значений по умолчанию и т. д.). убрать двусмысленность.

В результате мне нужен логический способ назвать мои CROSS APPLY, и я забочусь о производительности. Если количество CROSS APPLY изменяется, то, если CROSS APPLY нумеруются с помощью простого счетчика (например, вычислено1, вычислено2 и т. д.), то данное поле может увидеть изменение ссылки на свое имя с вычисляемого3.[ИМЯ ПОЛЯ] на вычисляемое4.[ПОЛЕ]. NAME], который влияет на всю оставшуюся часть запроса, который мог быть собран путем вызовов различных процедур C#. Это проблема технического обслуживания.

Альтернативой, которую я рассматриваю, является размещение каждого вычисляемого выражения в отдельном CROSS APPLY, а имя CROSS APPLY будет получено из псевдонима выражения. Например:

Использование одного CROSS APPLY:

CROSS APPLY (
    SELECT
          [TIV_BLDG] = (CASE [COVERAGE] WHEN 'TIV_BLDG' THEN VALUEAMT ELSE 0 END)

        , [TIV_OSTR] = (CASE [COVERAGE] WHEN 'TIV_OSTR' THEN VALUEAMT ELSE 0 END)

        , [TIV_CONT] = (CASE [COVERAGE] WHEN 'TIV_CONT' THEN VALUEAMT ELSE 0 END)

        , [TIV_TIME] = (CASE [COVERAGE] WHEN 'TIV_TIME' THEN VALUEAMT ELSE 0 END)

) computed2

Используя четыре CROSS APPLY:

CROSS APPLY (SELECT [TIV_BLDG] = (CASE [COVERAGE] WHEN 'TIV_BLDG' THEN VALUEAMT ELSE 0 END)) AS [TIV_BLDG_COMP]

CROSS APPLY (SELECT [TIV_OSTR] = (CASE [COVERAGE] WHEN 'TIV_OSTR' THEN VALUEAMT ELSE 0 END)) AS [TIV_OSTR_COMP]

CROSS APPLY (SELECT [TIV_CONT] = (CASE [COVERAGE] WHEN 'TIV_CONT' THEN VALUEAMT ELSE 0 END)) AS [TIV_CONT_COMP]

CROSS APPLY (SELECT [TIV_TIME] = (CASE [COVERAGE] WHEN 'TIV_TIME' THEN VALUEAMT ELSE 0 END)) AS [TIV_TIME_COMP]

Если я использую этот подход с несколькими CROSS APPLY, я могу легко генерировать имена, которые не изменятся, если я добавлю новые приложения или удалю их, и я могу предсказать в коде, который ссылается на поля, каким будет псевдоним таблицы. Однако это означает гораздо больше операторов CROSS APPLY. Каковы последствия производительности? Есть ли лучший способ сделать это, используя CROSS APPLY или какую-либо другую функцию SQL Server? (Мне не нужно, чтобы это была кросс-база данных, поэтому функции только Microsoft в порядке.)


person Paul Chernoch    schedule 10.07.2012    source источник
comment
Нит: планировщик запросов должен уметь сворачивать дополнительные псевдонимы (например, полностью удалять их из плана) в рамках правил RA. Он должен даже удалять выбранные значения, на которые не ссылаются, и уменьшать этот факт, и т. д. В любом случае план запроса должен быть первым местом, на которое следует обращать внимание для выявления узких мест в производительности.   -  person    schedule 10.07.2012
comment
Во всяком случае, я использую некоторую автоматическую генерацию SQL (без перекрестных применений, но много вложенных объединений и некоторых объединений и т. д.). Чтобы обработать изменение имени столбца, я также отслеживаю имя столбца при каждом выборе (я возвращаю структуру, представляющую имена столбцов и целевую таблицу/псевдоним). Затем на каждом уровне я повторно генерирую структуру на основе нового выбранного представления и обновляю/отбрасываю столбцы и целевую таблицу/псевдонимы. Используя этот подход, я избегаю большей части жесткого кодирования псевдонимов между уровнями и разрешаю окончательным/внешним запросам выбирать только внутренние столбцы по мере необходимости. SQL Server любит это.   -  person    schedule 10.07.2012


Ответы (1)


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

SQL Server может видеть CROSS APPLY и преобразовывать их в простые сложенные «вычислительные скаляры».

Другой потенциальной проблемой может быть размер запроса. Не уверен, есть ли какие-либо соответствующие ограничения с точки зрения количества AST-узлов или соединений или около того (я полагаю, что CROSS APPLY считается соединением, когда речь идет о внутренних ограничениях).

Помимо этих проблем, я думаю, что CROSS APPLY — очень хорошее и быстрое решение.

person usr    schedule 10.07.2012