Будет ли индекс использоваться при использовании предложения OR в - PullRequest
2 голосов
/ 13 июля 2010

Я написал хранимую процедуру с необязательными параметрами.

 CREATE PROCEDURE dbo.GetActiveEmployee
   @startTime DATETIME=NULL,
   @endTime   DATETIME=NULL
 AS
   SET NOCOUNT ON

   SELECT columns
   FROM table
   WHERE (@startTime is NULL or table.StartTime >= @startTime) AND
         (@endTIme is NULL or table.EndTime <= @endTime)

Мне интересно, будут ли использоваться индексы StartTime и EndTime?

Ответы [ 6 ]

4 голосов
/ 13 июля 2010

Да, они будут использоваться (возможно, проверьте план выполнения, но я знаю, что необязательность ваших параметров не должна иметь никакого значения)

Если у вас проблемы с производительностьюзапрос, то это может быть результатом перехвата параметров.Попробуйте следующий вариант вашей хранимой процедуры и посмотрите, имеет ли это какое-либо значение:

CREATE PROCEDURE dbo.GetActiveEmployee
    @startTime DATETIME=NULL,
    @endTime   DATETIME=NULL
AS
    SET NOCOUNT ON

    DECLARE @startTimeCopy DATETIME
    DECLARE @endTimeCopy DATETIME
    set @startTimeCopy = @startTime
    set @endTimeCopy = @endTime

    SELECT columns
    FROM table
    WHERE (@startTimeCopy is NULL or table.StartTime >= @startTimeCopy) AND
         (@endTimeCopy is NULL or table.EndTime <= @endTimeCopy)

Это отключает анализ параметров (SQL-сервер использует фактические значения, переданные SP для оптимизации) - В прошлом я 'исправив некоторые странные проблемы с производительностью, я все еще не могу удовлетворительно объяснить, почему, однако.

Еще одна вещь, которую вы, возможно, захотите попробовать, - это разделить ваш запрос на несколько различных операторов в зависимости от NULL-ности ваших параметров.:

IF @startTime is NULL
BEGIN
    IF @endTime IS NULL
        SELECT columns FROM table
    ELSE
        SELECT columns FROM table WHERE table.EndTime <= @endTime
END    
ELSE
    IF @endTime IS NULL
        SELECT columns FROM table WHERE table.StartTime >= @startTime
    ELSE
        SELECT columns FROM table WHERE table.StartTime >= @startTime AND table.EndTime <= @endTime
BEGIN

Это грязно, но, возможно, стоит попробовать, если у вас возникли проблемы, потому что это помогает, потому что сервер SQL может иметь только один план выполнения на оператор SQL, однако ваш оператор потенциально можетвозвращает очень разные наборы результатов.

Например, если вы передадите NULL и NULL, вы вернете всю таблицу и наиболее оптимальный план выполнения, однако если вы передадите небольшой диапазон дат, более вероятно, чтопоиск строки будет наиболее оптимальным планом выполнения.

С этим запросом в качестве одного оператора SQL-сервер вынужден выбирать между этими двумя параметрами, и поэтому план запроса, вероятно, будет неоптимальным в определенных ситуациях.Однако, разделив запрос на несколько операторов, SQL-сервер может иметь разные планы выполнения в каждом случае.

(Вы также можете использовать функцию / 1012 * динамический SQL для достижения того же результата, если хотите)

2 голосов
/ 13 июля 2010

Есть отличная статья, касающаяся критериев динамического поиска в SQL.Метод, который я лично использую в этой статье, - это стиль X = @ X или @X IS NULL с добавлением OPTION (RECOMPILE) в конце.Если вы прочитаете статью, она объяснит, почему

http://www.sommarskog.se/dyn-search-2008.html

1 голос
/ 13 июля 2010

Динамическое изменение поисков на основе заданных параметров - сложная тема, и выполнение одного способа по другому, даже с очень небольшим отличием, может иметь серьезные последствия для производительности.Ключ в том, чтобы использовать индекс, игнорировать компактный код, игнорировать беспокойство по поводу повторения кода, вы должны составить хороший план выполнения запроса (используйте индекс).

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

Условия динамического поиска в T-SQL by Erland Sommarskog

Проклятие и благословения динамического SQL Эрланда Соммарскога

Часть вышеупомянутых статей, которые относятся к этому запросу, является Сумкой Уловок Умачандара , но в основном это по умолчаниюпараметры до некоторого значения, чтобы исключить необходимость использования ИЛИ.Это даст лучшее использование индекса и общую производительность:

CREATE PROCEDURE dbo.GetActiveEmployee
    @startTime DATETIME=NULL,
    @endTime   DATETIME=NULL
AS
    SET NOCOUNT ON

    DECLARE @startTimeCopy DATETIME
    DECLARE @endTimeCopy DATETIME
    set @startTimeCopy = COALESCE(@startTime,'01/01/1753')
    set @endTimeCopy = COALESCE(@endTime,'12/31/9999')

    SELECT columns
    FROM table
    WHERE table.StartTime >= @startTimeCopy AND table.EndTime <= @endTimeCopy)
1 голос
/ 13 июля 2010

Да, в зависимости от запроса могут использоваться индексы или включающие столбцы StartTime и EndTime.

Однако, [variable] IS NULL OR... делает запрос несортируемым. Если вы не хотите использовать оператор IF (поскольку CASE является выражением и его нельзя использовать для управления логикой принятия решения о потоке), динамический SQL является следующей альтернативой для производительного SQL.

IF @startTime IS NOT NULL AND @endTime IS NOT NULL
BEGIN

  SELECT columns
    FROM TABLE 
   WHERE starttime >= @startTime
       AND endtime <= @endTime

END
ELSE IF @startTime IS NOT NULL
BEGIN

  SELECT columns
    FROM TABLE 
   WHERE endtime <= @endTime

END    
ELSE IF @endTIme IS NOT NULL
BEGIN

  SELECT columns
    FROM TABLE
   WHERE starttime >= @startTime

END
ELSE
BEGIN

  SELECT columns
     FROM TABLE

END
0 голосов
/ 13 июля 2010

Наверное, нет.Посмотрите на эту запись в блоге от Tony Rogerson MVP SQL Server:

http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/05/17/444.aspx

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

0 голосов
/ 13 июля 2010

Не думаю, что вы можете гарантировать, что индекс будет использован. Это будет сильно зависеть от размера таблицы, отображаемых столбцов, структуры индекса и других факторов.

Лучше всего использовать SQL Server Management Studio (SSMS), выполнить запрос и включить «Фактический план выполнения». Затем вы можете изучить это и увидеть, какие именно индексы или индексы были использованы.

Вы часто будете удивлены тем, что найдете.

Это особенно верно, если в запросе есть OR или IN.

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