Порядок внутри оператора IN

Рейтинг: 1Ответов: 2Опубликовано: 03.02.2015

У меня простой вопрос, влияет ли на скорость порядок ID внутри оператора IN? Например,

SELECT * FROM test WHERE id IN (221258, 121257, 977256, 2255, 52223, 50, 222222)

будет ли выполняться дольше, чем

SELECT * FROM test WHERE id IN (50, 2255, 52223, 121257, 221258, 222222, 977256) ?

Синтетические тесты не показали существенной разницы, но как на самом деле?

Ответы

▲ 1

Список значений в предикате IN лучше перечислять от более часто используемых к менее. Тогда если сравниваемое значение присутствует в списке, оно будет отобрано быстрей. Если значение отсутствует в списке, то все равно будет просмотрен весь список.

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

UPD. Сделал простой тест. Поскольку в основном работаю с SQL Server, то на нём.

Генерация данных:

create table Tin (id int)
declare @N int=1000000
declare @i int =1
set nocount on;
while @i<100
begin
insert into Tin values(@i)
set @i=@i+1
end
while @i<=1000000
begin
insert into Tin values(999)
set @i=@i+1
end

Запросы:

select * from tin where 
ID in(100,101,102,103,104,105,106,107,108,109,999)
go
select * from tin where 
ID in(999,100,101,102,103,104,105,106,107,108,109)

Результаты (второй запрос показывает стабильно лучшие результаты по elapsed time):

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(999901 row(s) affected)

 SQL Server Execution Times:
   CPU time = 1248 ms,  elapsed time = 17998 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(999901 row(s) affected)

 SQL Server Execution Times:
   CPU time = 1264 ms,  elapsed time = 15905 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 57 ms.

UPD2 Должен отказаться от своего предположения, по крайней мере, для SQL Server. В плане указан отсортированный список значений в IN. Вероятно, сервер выполняет сортировку значений перед сравнением. Так что при большом числе прогонов, результаты должны быть практически одинаковыми.

▲ 0

Провёл с десяток разных тестов, с учётом погрешностей результаты были практически одинаковы. Лучшее время показывал то сортированный, то нет.

Пробовал запрашивать по 1000 раз запросы с одинаковыми сортированными значениями IN и не сортированными. Пробовал тоже самое, но добавлял рандомные ID в IN. База содержала >1млн записей, список внутри IN был ~20 ID.

Преимущества сортировки во время тестов я не заметил.

Для себя сделал вывод, что можно не париться над сортировкой.