Оптимальные поисковые запросы - PullRequest
2 голосов
/ 07 мая 2010

Исходя из моего последнего вопроса Производительность запросов к SQL Server и обнаружение, что мой метод разрешения дополнительных параметров в поисковом запросе неоптимален, есть ли у кого-нибудь рекомендации о том, как к этому подойти?

Например, скажем, у меня есть таблица приложения, таблица клиента и таблица контактных данных, и я хочу создать SP, который позволит выполнять поиск по некоторым, ни по одной или по всей фамилии, домашнему телефону, мобильному телефону и идентификатору приложения, я могу используйте что-то вроде следующего:

select *
from application a inner join customer c on a.customerid = a.id
    left join contact hp on (c.id = hp.customerid and hp.contacttype = 'homephone')
    left join contact mob on (c.id = mob.customerid and mob.contacttype = 'mobile')
where (a.ID = @ID or @ID is null)
    and (c.Surname = @Surname or @Surname is null)
    and (HP.phonenumber = @Homphone or @Homephone is null)
    and (MOB.phonenumber = @Mobile or @Mobile is null)

Схема, использованная выше, нереальна, и я бы не использовал select * в сценарии реального мира, это конструкция интересующего меня предложения where. Есть ли лучший подход, динамический sql или альтернатива, которая может достичь того же результата, без необходимости использования множества вложенных условных выражений. Некоторые СП могут иметь 10–15 критериев, используемых таким образом

Ответы [ 3 ]

3 голосов
/ 07 мая 2010

Для этого не существует подхода к запросу "один размер подходит всем", а то, как вы это делаете, имеет незначительные последствия для производительности.Если вы хотите выйти за рамки простого запроса правильного ответа, независимо от того, насколько он медленный, посмотрите на эту статью: Условия динамического поиска в T-SQL Эрланда Соммарскога .Он охватывает каждый метод и дает подробные сведения о плюсах и минусах каждого метода.

Если вы можете определить минимальный и максимальный возможные диапазоны для вашего столбца поиска, а столбец поиска НЕ ​​НЕДЕЙСТВИТЕЛЕН, то вы можетелучше, чем (@Search IS NULL ИЛИ Col = @ Search), см. эту область вышеупомянутой связанной статьи .Однако вам следует прочитать всю статью, так как существует множество вариантов, которые зависят от вашей ситуации, вам действительно нужно изучить несколько подходов и когда их использовать.

Также посмотрите этот другой недавний ответ: SQL Server2008 - условный запрос

1 голос
/ 07 мая 2010

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

Вы должны определить набор индексов, которые вы хотите использовать, и написать отдельный запрос для каждого набора, заменив OR в индексированных полях на UNION ALL:

SELECT  *
FROM    tables
WHERE   A = @ID
        AND (c.Surname = @Surname or @Surname IS NULL)
        AND (HP.phonenumber = @Homphone or @Homephone IS NULL)
        AND (MOB.phonenumber = @Mobile or @Mobile IS NULL)
UNION ALL
SELECT  *
FROM    tables
WHERE   @ID IS NULL
        AND c.Surname = @Surname
        AND (HP.phonenumber = @Homphone or @Homephone IS NULL)
        AND (MOB.phonenumber = @Mobile or @Mobile IS NULL)
UNION ALL
SELECT  *
FROM    tables
WHERE   @ID IS NULL
        AND @Surname IS NULL
        AND (HP.phonenumber = @Homphone or @Homephone IS NULL)
        AND (MOB.phonenumber = @Mobile or @Mobile IS NULL)
1 голос
/ 07 мая 2010

Хорошо, мы идем

ОПЦИЯ (РЕКОМЕНДУЕТСЯ)

является обязательным - в противном случае первый план запроса используется повторно, независимо от соответствия параметров. Извините, нет лучшего способа сделать это лучше.

Кроме того - нет, извините. Динамический SQL может стать более эффективным (исключая альтернативы IS NULL), но вы, по сути, используете его, если это невозможно.

При использовании динамического SQL у вас практически нет aline для HP.phonenumber, если переменная HomePhone равна нулю;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...