2015-04-15 3 views
0

У меня есть запрос следующим образом:SQL Server, запрос с использованием указательного, но все еще медленно

SELECT 1 
FROM [Call] 
INNER JOIN [Caller] ON [Call].callerId = [Caller].id 
WHERE [Call].[phoneNumber] = @phoneNumber 
AND 
[Caller].callerType = @callerType 
AND 
[Call].[time] > @time 
AND 
[Call].[status] = @status 
AND 
[Call].[type] <> @type 

Существует кластерный первичный ключ индекс на [Caller]id колонка. Существует не-кластерный индекс [Call] следующим образом:

CREATE INDEX IX_callerId_time_phonenumber_status_type 
ON dbo.[Call] 
(
    [callerId] ASC, 
    [time] ASC, 
    [phoneNumber] ASC, 
    [status] ASC, 
    [type] ASC 
) 

я замечаю в плане исполнения, что 90% от стоимости моего запроса выглядит следующим образом:

Predicate: 
[Call].[status] = 10 AND [Call].[type] <> 10 

Object: 
[Call].[IX_callerId_time_phonenumber_status_type] 

Так он использует право но я все еще плохо себя чувствую. Есть идеи?

+0

Это сканирование индекса правильно? Ваше неравенство в предикате потенциально делает предикат nonSARGable. Просто изменив на call.type> 10 ИЛИ call.type <10, вероятно, сделает вместо этого поиск. –

+0

Только столбец «время» используется для перемещения по дереву. Нет ничего, что сужает обход вниз - все это будет всего лишь предикатом фильтра. Вы должны всегда индексировать сначала по принципу равенства, а не по диапазонам. –

+0

@SeanLange это уже уже поиск. – ashishduh

ответ

0

Predicate [Call].[time] > @time является довольно неселективным, но структура вашего индекса заставляет SQL Server придавать ему приоритет над некоторыми другими критериями, которые, вероятно, более избирательны. Вероятно, он предпочитает сканировать большой кусок индекса для каждого callerId. Упорядочивание индекс, как так, вероятно, повысить производительность для данного конкретного запроса:

CREATE INDEX IX_callerId_time_phonenumber_status_type 
ON dbo.[Call] 
(
    [callerId] ASC, 
    [phoneNumber] ASC, 
    [status] ASC, 
    [time] ASC, 
    [type] ASC 
) 
+0

Эта таблица имеет более 100 миллионов строк, возвращающихся на 10 лет, поэтому я думал, что время должно быть выше в приоритетном порядке, особенно потому, что запросы в основном запрашивают последние данные. Учитывая, что, по-вашему, должен выглядеть индекс? – ashishduh

+0

@ghettojoe, возможно, стоит попробовать в обоих направлениях. Если бы мне пришлось это догадаться, я бы все равно поместил свои деньги в том порядке, который я предлагал. Он должен заканчивать сканирование гораздо меньшим количеством строк индекса, но это будет смягчено тем, что эти строки будут более широко разбросаны. Заметьте, что я говорю только о влиянии на * этот * запрос. –

0

Не зная, «Время» действительно время тип данных или тип данных VARCHAR, я бы предложил следующий индекс.

CREATE NONCLUSTERED INDEX IX_callerId_time_phonenumber_status_type 
ON [dbo].[Call] ([PhoneNumber],[Status],[Time],[Type]) 
0

Вы исключили параметр sniffing? Удивительно, если оптимизатор застрял на некоторых не очень хороших значениях.

Это мой любимчик статья http://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/

+0

Другая ссылка http://blogs.msdn.com/b/turgays/archive/2013/09/10/parameter-sniffing-problem-and-workarounds.aspx – discosammy

Смежные вопросы