powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Что будет быстрее
9 сообщений из 9, страница 1 из 1
Что будет быстрее
    #32046883
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
Добрый день.
Задача следующая, написать процедуру которая будет возвращать данные
Варианты решения (код несколько упрощен, чтобы была понятнее суть вопроса)
1.
Код: plaintext
1.
2.
SELECT      Код, Заказ
FROM         [Заказы строки]
where ((@код is Null) OR (Код=@код)) AND ((@заказ is NULL) OR (Заказ = @заказ))

2.
Код: plaintext
1.
2.
3.
4.
5.
6.
SET @sql = ‘SELECT      Код, Заказ
FROM         [Заказы строки]
where ((@код is Null) OR (Код=@код)) AND ((@заказ is NULL) OR (Заказ = @заказ))’

SET @sql = REPLACE (@sql, '@код', IsNull (CONVERT (varchar, @код), 'NULL'))
SET @sql = REPLACE (@sql, '@заказ', IsNull (CONVERT (varchar, @заказ), 'NULL'))
Exec(@sql)

Т.е. на самом деле динамически будет вызываться запрос, например

Код: plaintext
1.
exec('SELECT      Код, Заказ FROM         [Заказы  строки]
where ((1 is Null) OR (Код=1)) AND ((1 is NULL) OR (Заказ = 1)) ')


Вопрос в том что будет работать быстрее.
В первом варианте план запроса (как обещает Microsoft) будет построен один раз при первом вызове процедуры, который будет явно менее оптимален чем план запроса когда условие 1 is Null сразу отбросится.
Во втором случае план запроса получится вроде оптимальным, но тогда каждый раз будет производиться разбор запроса, да еще и потери времени при динамическом выполнении запроса. Кроме того запрос во втором случае не кэшируется.
...
Рейтинг: 0 / 0
Что будет быстрее
    #32046915
AAron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На самом деле запрос не особо тяжелый, поэтому не думаю, что есть смысл заморачиваться на скорость компиляции, в любом случае, при единичный запросах она не составит какое-то заметное время. разве что вместо replace использовать другие конструкции. Я бы предложил два вариант (см.ниже)...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
SELECT @SQL = '

    SELECT      Код, Заказ
    FROM         [Заказы строки]
    WHERE
        (' + ISNULL('Код=' + cast(@код as varchar( 15 )), '1' ) + '
        AND (' + ISNULL('Заказ =' + cast(@заказ as varchar( 15 )), '1' )
'


либо в условии WHERE использовать
Код: plaintext
1.
2.
3.
4.
5.
COALESCE(
        'Код='+cast(@код as varchar( 15 )) + ' and Заказ =' + cast(@Заказ as varchar( 15 )),
        'Код='+cast(@код as varchar( 15 )),
        'Заказ =' + cast(@Заказ as varchar( 15 ))
)
...
Рейтинг: 0 / 0
Что будет быстрее
    #32046929
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
Решил дописать
Запрос указан для примера и на практике может быть и очень сложным, а количество пользователей довольно большим, поэтому и интересует скорость выполнения.
...
Рейтинг: 0 / 0
Что будет быстрее
    #32046945
dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да незачем тут использовать динамический SQL запрос. Хотите чтоб каждый раз план составлся заново - используйте with recompile.
...
Рейтинг: 0 / 0
Что будет быстрее
    #32046952
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если количество запросов велико то время будет одинаково... запросы перекомпилится будут редко...
небольшие затраты на разбор и выяснение того что такой запрс уже был , и возьмется из кэша....
...
Рейтинг: 0 / 0
Что будет быстрее
    #32046956
SM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
SELECT      Код, Заказ
FROM         [Заказы строки]
where ((@код is Null) OR (Код=@код)) AND ((@заказ is NULL) OR (Заказ = @заказ))



Посмотри на план выполнения запроса - индексы по Код и Заказ (если они есть ) использоваться не будут.

То же самое будет и с твоим динамическим запросом
Код: plaintext
1.
exec('SELECT      Код, Заказ FROM         [Заказы  строки]
where ((1 is Null) OR (Код=1)) AND ((1 is NULL) OR (Заказ = 1)) ')


Лучше всего будет самому составлять WHERE когда нужно и только для нужных параметров
...
Рейтинг: 0 / 0
Что будет быстрее
    #32047046
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
Попробую немного покритиковать предложения
самому формировать предложение where
Бесспорно - это было-бы оптимально, но приходится писать код. Писать код - это время ну и т.д.

не использовать динамический SQL а писать WITH RECOMPILE
не помогает, насколько я понимаю по причине того что сначала процедура перекомпилится, а уж потом будет разбираться какие ей там параметры пришли

не будут использоваться индексы если писать OR
смотрел Execution Plan - используются индексы как надо.
...
Рейтинг: 0 / 0
Что будет быстрее
    #32047151
Фотография akuz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
SELECT Код, Заказ
FROM [Заказы строки]
where Код = ISNULL(@код,Код)
AND Заказ = ISNULL(@заказ,Заказ)

Если Заказ NULLABLE то
Код: plaintext
AND ISNULL(Заказ, 0 ) = ISNULL(@заказ,ISNULL(Заказ, 0 ))
...
Рейтинг: 0 / 0
Что будет быстрее
    #32047199
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
2 Akuz
Вряд ли так будет быстрее работать, достаточно посмотреть план и убедиться, что случае Код=Код MS SQL все равно будет искать по этому условию, но не отбрасывать его как в случае null is null

И еще, вы меня не правильно поняли. Меня не интересует как так написать запрос чтобы он быстрее работал с Replace или с IsNull или еще как. Запрос я привел для примера, чтобы легче было объяснить проблему.
Меня интересует, что на практике или в теории будет работать быстрее в хранимой процедуре вариант 1 или вариант 2. Я понимаю что для приведенного примера все равно, но в реальности запрос может связывать 20 и более таблиц, а условии where участвовать 20 и более критериев поиска. Вот в этом случае и вознакает проблема когда может понадобиться отбирать по одному критерию как
Код: plaintext
1.
2.
SELECT Код, Заказ
FROM [Заказы строки]
where Код =  1 

а может по нескольким
Код: plaintext
1.
2.
SELECT Код, Заказ
FROM [Заказы строки]
where Код =  1  AND Заказ =  1 

Согласитесь не совсем одинаково, если учесть что реальный запрос (не из примера) очень сложный и данных очень много
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Что будет быстрее
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]