Оптимизация SQL-запросов - PullRequest
       26

Оптимизация SQL-запросов

1 голос
/ 21 февраля 2011

У меня есть несколько вопросов по поводу моего запроса.Я называю эту процедуру хранения на своей первой странице, поэтому для меня важно, достаточно ли она оптимизирована.

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

Select top (@NumberOfRows) 
    ...     
from(
    SELECT  
            row_number() OVER (ORDER BY tblEventOpen.TicketAt, tblEvent.EventName, tblEventDetail.TimeStart) as RowNumber
            , ...                    
    FROM    --[...some inner join logic...]
    WHERE     
            (tblEventOpen.isValid = 1) AND (tblEvent.isValid = 1) and 
            (tblCondition_ResellerDetail.ResellerID = 1) AND 
            (tblEventOpen.TicketAt >= GETDATE()) AND 
            (GETDATE() BETWEEN 
                            DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.StartTime) , tblEventOpen.TicketAt) 
                        AND DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.EndTime) , tblEventOpen.TicketAt))
) as t1
where RowNumber >= (@PageNumber -1) * @NumberOfRows and 
    (@city='' or @city is null or city like @city) and 
    (@At is null or @At=At) and 
    (@TimeStartInMinute=-1 or @TimeStartInMinute=TimeStartInMinute) and
    (@EventName='' or EventName like @EventName) and
    (@CategoryID=-1 or @CategoryID = CategoryID) and
    (@EventID is null or @EventID = EventID) and
    (@DetailID is null or @DetailID = DetailID)
ORDER BY RowNumber
  1. Я беспокоюсь об этой части:

    (GETDATE() BETWEEN DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.StartTime) , tblEventOpen.TicketAt) AND DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.EndTime) , tblEventOpen.TicketAt))
    Как выполняется таблица t1?Я имею в виду, после того как я поместил некоторое выражение where после t1 (строка 17 и далее), фильтрует ли оно элементы после выполнения t1?например, я отфильтрую результат по числу, равному 10, так что это означает, что внутренний выбор (...) as t1 вернет только 10 элементов, или он выберет все элементы, тогда мой внешний выбор займет 10 из них?

  2. Я хочу отфильтровать свой результат по некоторым необязательным параметрам, поэтому я поставил что-то вроде @DetailID is null or @DetailID = DetailID, это хороший способ?

  3. Что-нибудь еще, что я должен рассмотреть, чтобы сделать это быстрее (более оптимизировать)?

Ответы [ 2 ]

2 голосов
/ 25 февраля 2011

Мой комментарий к вашему запросу:

  1. Вы правы, вы должны беспокоиться о состоянии "GETDATE() BETWEEN ...".Сравнение значения с функцией, включающей более 1 таблицы, скорее всего, будет сканировать все пространство поиска.Упростите ваше условие или, если возможно, добавьте вычисляемый столбец для такой функции
  2. Поместите все условия, кроме "RowNumber >= ...", во внутренний запрос
  3. Можно ставить необязательные условия так, как вы это делаете.Я тоже это делаю: -)
  4. Убедитесь, что у вас есть индекс, по крайней мере, один для каждого столбца, используемого в предложении where в качестве первого столбца индекса, а затем первичного ключа.Было бы лучше, если бы ваш первичный ключ был кластеризован

Ну, это основано на моем собственном опыте.Это может или не может быть применимо к вашей ситуации.

[ОБНОВЛЕНИЕ] Вот полный запрос

Select top (@NumberOfRows)
    ...    
from(
    SELECT  
            row_number() OVER (ORDER BY tblEventOpen.TicketAt, tblEvent.EventName, tblEventDetail.TimeStart) as RowNumber
            , ...                    
    FROM    --[...some inner join logic...]
    WHERE    
            (tblEventOpen.isValid = 1) AND (tblEvent.isValid = 1) and
            (tblCondition_ResellerDetail.ResellerID = 1) AND
            (tblEventOpen.TicketAt >= GETDATE()) AND
            (GETDATE() BETWEEN
                            DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.StartTime) , tblEventOpen.TicketAt)
                        AND DATEADD(minute, (tblEventDetail.TimeStart - 60 * tblCondition_ResellerDetail.EndTime) , tblEventOpen.TicketAt)) and
            (@city='' or @city is null or city like @city) and
            (@At is null or @At=At) and
            (@TimeStartInMinute=-1 or @TimeStartInMinute=TimeStartInMinute) and
            (@EventName='' or EventName like @EventName) and
            (@CategoryID=-1 or @CategoryID = CategoryID) and
            (@EventID is null or @EventID = EventID) and
            (@DetailID is null or @DetailID = DetailID)
) as t1
where RowNumber >= (@PageNumber -1) * @NumberOfRows
ORDER BY RowNumber
1 голос
/ 07 марта 2011

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

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

В SSMS вы можете нажать «Запрос» ---> «Включить фактический план выполнения» перед выполнением запроса. (Ctrl + M) это сочетание клавиш.

Затем выполните ваш запрос. SSMS создаст новую вкладку в области результатов. Который покажет вам, как механизм SQL выполняет ваш запрос, вы можете навести курсор на каждый узел для получения дополнительной информации. cost % будет особенно интересным, что позволит вам увидеть самую дорогую часть вашего запроса.

Сложно дать вам совет без этого плана выполнения, поэтому многие люди прокомментировали ваш вопрос. Ваша схема и индексы изменяют способ выполнения запроса, поэтому кто-то не может точно воспроизвести его в своей среде без сценариев для таблиц / индексов и т. Д. Даже в этом случае статистика может быть устаревшей и могут возникнуть другие проблемы.

Вы также можете выполнить SET STATISTICS PROFILE ON, чтобы получить текстовое представление плана (может быть полезно обратиться за помощью).

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

http://msdn.microsoft.com/en-us/library/ms178071.aspx

Анализ плана запросов SQL Server

Основы плана выполнения

...