Динамический порядок при использовании порядка по - ускорение - PullRequest
4 голосов
/ 13 декабря 2011

Я использую номер строки, чтобы получить постраничные результаты из хранимой процедуры.

Я обнаружил, что упорядочение с использованием динамического имени столбца оператора case замедляет процесс - но если я жестко закодирую порядок по всемХорошо.

Есть ли способ ускорить динамический порядок, не делая ВСЕ SQL-запрос на одну строку и используя SP_EXECUTESQL

            ROW_NUMBER() OVER (ORDER BY 
            CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 0 THEN CLH.IdentityValue END DESC,
            CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 1 THEN CLH.IdentityValue END
            --CLH.CustomerName

            ) AS [ROW]

Ответы [ 4 ]

1 голос
/ 13 декабря 2011

При использовании одного запроса с использованием разных индексов на основе значений параметров в SQL Server не поддерживается. AFAIK, есть два решения этого:

  • Создайте динамический запрос в хранимой процедуре и используйте sp_executesql
  • Построение динамического запроса на стороне клиента

На практике приложению PHP и .NET сложно делиться кодом. Или даже для разных версий .NET. Это делает первый вариант более сильным.

Так что лучший способ сделать это - использовать динамический SQL. И да, это довольно удивительно. :)

1 голос
/ 13 декабря 2011

Проблема в том, что SQL Server пытается построить ОДИН план выполнения, чтобы соответствовать всем параметрам.Это означает, что он не меняет своего мнения и выбирает другой индекс, когда вы задаете ему другие параметры.(Часть different index важна, поскольку нагрузка переупорядочения неподходящего индекса может быть очень высокой.)

Единственный способ для этого - создать новый план выполнения, который включает динамический SQL- Именно то, что вы хотите избежать.

Однако;динамический SQL и SP_EXECUTESQL не обязательно плохая идея.Так как он также может быть параметризован, правильное использование позволяет повторное использование плана выполнения и может быть исключительно эффективным при решении подобных проблем.

Есть ли конкретная причина, по которой вам нужно избегать динамического SQL?

Единственный реальный обходной путь - это написать запрос несколько раз с разным порядком и выбрать, какой из них использовать с блоками T-SQL IF.Это позволит оптимизатору генерировать различные планы выполнения.

0 голосов
/ 13 декабря 2011

Попробуйте несколько операторов ROW_NUMBER, чтобы у вас было меньше обработки для сортировки

   ROW_NUMBER() OVER (ORDER BY CLH.IdentityValue) DESC AS rnDesc,
   ROW_NUMBER() OVER (ORDER BY CLH.IdentityValue) AS rnAscDesc,
   ...
ORDER BY
   CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 0 THEN rnDesc END,
   CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 1 THEN rnDesc END
0 голосов
/ 13 декабря 2011

Одна вещь, которую вы могли бы попробовать, - это объединить два предложения case в один регистр, например:

(ORDER BY 
        CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 0 
                 THEN CLH.IdentityValue*-1
             WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending  = 1 
                 THEN CLH.IdentityValue 
        END
 )

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

...