Я пытаюсь оптимизировать сложный SQL-запрос и получаю дико различные результаты, когда я вношу на вид несущественные изменения.
Например, это берет 336 мс для выполнения:
Declare @InstanceID int set @InstanceID=1;
With myResults as (
Select
Row = Row_Number() Over (Order by sv.LastFirst),
ContactID
From DirectoryContactsByContact(1) sv
Join ContainsTable(_s_Contacts, SearchText, 'john') fulltext on (fulltext.[Key]=ContactID)
Where IsNull(sv.InstanceID,1) = @InstanceID
and len(sv.LastFirst)>1
) Select * From myResults Where Row between 1 and 20;
Если я заменяю @InstanceID трудно кодированным числом, он принимает 13 секунд (13 890 мс) для выполнения:
Declare @InstanceID int set @InstanceID=1;
With myResults as (
Select
Row = Row_Number() Over (Order by sv.LastFirst),
ContactID
From DirectoryContactsByContact(1) sv
Join ContainsTable(_s_Contacts, SearchText, 'john') fulltext on (fulltext.[Key]=ContactID)
Where IsNull(sv.InstanceID,1) = 1
and len(sv.LastFirst)>1
) Select * From myResults Where Row between 1 and 20;
В других случаях я получаю эффект полной противоположности: Например, использование переменной @s вместо литерала 'Джон' делает запрос выполняемым более медленно порядком величины.
Кто-то может помочь мне связать это? Когда переменная делает вещи быстрее, и когда она делает вещи медленнее?
Причина может быть в том, что IsNull(sv.InstanceID,1) = @InstanceID
очень избирателен для некоторых значений @InstanceID
, но не очень избирателен для других. Например, могут быть миллионы строк с InstanceID = null
, поэтому для @InstanceID = 1
сканирование может быть быстрее.
Но если вы явно указываете значение @InstanceID
, SQL Server на основе статистики таблицы знает, является ли оно выборочным или нет.
Сначала убедитесь, что ваша статистика актуальна:
UPDATE STATISTICS table_or_indexed_view_name
Затем, если проблема все еще возникает, сравните план выполнения запроса для обоих методов. Затем вы можете применить самый быстрый метод, используя подсказки запроса.