производительность условной хранимой процедуры и оператор построения кода - PullRequest
1 голос
/ 28 апреля 2020

В настоящее время я работаю над системой отчетов для нашего архива данных. Цель состоит в том, чтобы выбрать данные за каждый 1-й месяц, за каждый полный час и т. д. Итак, у меня есть куча параметров для выбора данных до одного часа.

Чтобы добиться этого, я использовал операторы CASE для корректировки выбора следующим образом:

SELECT
    MIN(cd.Timestamp) as Mintime,
    --Hours
    CASE
        WHEN
            @SelHour IS NOT NULL
        THEN
            DATEPART(HOUR, cd.Timestamp)
    END as Hour,
    ... -- more CASES up to DATEPART(YEAR, cd.Timestamp)
    FROM dbo.CustomerData cd
    ... -- filter data and other stuff 

Этот оператор работает хорошо для меня пока, но я немного беспокоюсь о производительности хранимой процедуры. Потому что я не знаю, как сервер будет вести себя с этим «изменяющимся» утверждением. Результат может варьироваться от 20 строк до 250 000 строк и более. В зависимости от заданных параметров. Насколько я знаю, сервер sql сохраняет план запроса и повторно использует его для будущего выполнения. Когда он сохраняет план для результата 20 рядов, производительность для результата 250.000, вероятно, довольно плохая.

Теперь мне интересно, какой подход лучше. Используя эту хранимую процедуру или создайте оператор внутри моего c# бэкэнда и передайте «скорректированный» оператор на сервер sql?

Спасибо и приветствия

1 Ответ

0 голосов
/ 28 апреля 2020

Для результирующего набора из 20 строк он будет работать в любом месте. Но для возврата 250k записей в c# код кажется измененным в дизайне для этого кода, так как загрузка 250k записей в памяти и циклы также потребляют значительную память, и такие одновременные запросы от другого сеанса / пользователя будут умножать загрузку в геометрической прогрессии.

В любом случае для решения проблемы с SQL Сервером, повторно использующим тот же план запросов, вы можете перекомпилировать планы запросов выборочно или каждый раз. Эти опции доступны для плана перекомпиляции:

  1. OPTION (RECOMPILE)

    SELECT MIN(cd.Timestamp) as Mintime, --Hours CASE WHEN @SelHour IS NOT NULL THEN DATEPART(HOUR, cd.Timestamp) END as Hour, ... -- more CASES up to DATEPART(YEAR, cd.Timestamp) FROM dbo.CustomerData cd ... -- filter data and other stuff OPTION(RECOMPILE)

  2. С параметром RECOMPILE это будет перекомпилировать план выполнения каждый раз

    CREATE PROCEDURE dbo.uspStoredPrcName @ParamName varchar(30) = 'abc'<br> WITH RECOMPILE<br> AS<br> ...

  3. РЕКОМЕНДАЦИЯ Запрос подсказка предоставление WITH RECOMPILE in execute

ПРИМЕЧАНИЕ: для этого потребуется разрешение CREATE PROCEDURE в базе данных и разрешение ALTER для схемы, в которой создается процедура.

EXECUTE uspStoredPrcName WITH RECOMPILE;<br> GO

sp_recompile Системная хранимая процедура

ПРИМЕЧАНИЕ: Требуется разрешение ALTER для указанной процедуры.

EXEC sp_recompile N'dbo.uspStoredPrcName ';<br> GO

Подробнее о перекомпиляции см. В документах Microsoft: https://docs.microsoft.com/en-us/sql/relational-databases/stored-procedures/recompile-a-stored-procedure?view=sql-server-ver15

...