Загадка производительности запросов T-SQL: Почему делает использование переменной, имеют значение?

Я пытаюсь оптимизировать сложный 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 вместо литерала 'Джон' делает запрос выполняемым более медленно порядком величины.

Кто-то может помочь мне связать это? Когда переменная делает вещи быстрее, и когда она делает вещи медленнее?

12
задан Herb Caudill 19 February 2010 в 02:45
поделиться

1 ответ

Причина может быть в том, что IsNull(sv.InstanceID,1) = @InstanceID очень избирателен для некоторых значений @InstanceID, но не очень избирателен для других. Например, могут быть миллионы строк с InstanceID = null, поэтому для @InstanceID = 1 сканирование может быть быстрее.

Но если вы явно указываете значение @InstanceID, SQL Server на основе статистики таблицы знает, является ли оно выборочным или нет.

Сначала убедитесь, что ваша статистика актуальна:

UPDATE STATISTICS table_or_indexed_view_name 

Затем, если проблема все еще возникает, сравните план выполнения запроса для обоих методов. Затем вы можете применить самый быстрый метод, используя подсказки запроса.

2
ответ дан 3 December 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: