2013-02-27 3 views
0

У меня есть следующий запрос. DataStaging - большой стол имеет 10 миллионов строк.Составной индекс, индекс и индекс дублированной колонки

Product i s меньший стол имеет 1000 рядов.

Нам нужно найти product_id с помощью ref и есть два ref (ref1,ref2) на Product столе, так должны присоединиться к таблице дважды.

UPDATE dbo.DataStaging 
    SET  ProductId = COALESCE(Ref1_Pid, Ref2_Pid, 0) 
    FROM dbo.DataStaging s 
      LEFT JOIN (SELECT id [Ref1_Pid] , 
           Ref1 
         FROM dbo.Product 
         WHERE isActive = 1 
        ) p1 ON s.[Ref] = p1.Ref1 
      LEFT JOIN (SELECT id [Ref2_Pid] , 
           Ref2 
         FROM dbo.Product 
         WHERE IsActive = 1 
        ) p2 ON s.[Ref] = p1.Ref2 

    WHERE s.TypeId = 1 
      AND s.StatusId = 2 

Это первичный ключ на столе продукт PK_Product и я свободен, чтобы добавить индекс Non_Clustered.

(1) Три индекса: NC_index на (IsActive), NC_Index на (Ref1), NC_Index на (REF2)

(2) двух составных индексов: NC_Index на (IsActive, REF1), NC_Index на (IsActive , Ref2)

(3) Один композитный индекс: NC_Index на (IsActive, Ref1, Ref2)

для (1) он сканирует таблицу, используя Первичный ключ PK_Product, но не индекс ЧПУ.

для (2) он использует сканирование NC_index для каждого индекса.

для (3) Он использует NC_index сканирование на том же самом индексе, но размер строки является двойником (2)

В результате производительность (2)> (3)> (1)

Мой вопрос,

Почему нет (1) сканирования по индексу NC?

Каков недостаток, если я создаю индекс вроде (2) или (3)?

Предположим, приведенный выше запрос является самым тяжелым процессом Product, но есть сотни stored procs с помощью product таблицы с select заявления с различными where состояния. Является ли (2) хорошим подходом, чем (3), даже производительность для вышеуказанного запроса равна (2)> (3)?

(игнорировать индекс dataStaging на данный момент)

ответ

1

(1) потребовало бы индекс присоединиться к индексу на IsActive и один на REF1/Ref2, что она Диминг меньше оптимального.

Я бы пойти на вариацию (2) - два отфильтрованных индексов, которая включает:

create index IX_Product_Ref1 on Product (Ref1) include(id) where (IsActive = 1) 
create index IX_Product_Ref2 on Product (Ref2) include(id) where (IsActive = 1) 

(3) будет только хорошая идея, если вы запрашиваете IsActive, REF1 И ref2 вместе.

Кроме того, не могли бы вы написать свой запрос следующим образом?

UPDATE dbo.DataStaging 
    SET  ProductId = isnull(p.id, p2.id) 
FROM dbo.DataStaging s 
LEFT JOIN dbo.Product p ON s.[Ref] = p.Ref1 and p.IsActive = 1 
LEFT JOIN dbo.Product p2 ON s.[Ref] = p2.Ref2 and p2.IsActive = 1 
WHERE s.TypeId = 1 
AND s.StatusId = 2 
+0

Спасибо за ваш ответ muhmud, я никогда не использую отфильтрованные индексы, прочитаю его позже. Я прочитал из другого сообщения ppls, в котором говорится: «left join ... or..' хуже, чем использовать два' left join', но не уверен снова. –

+0

Да, я думал об этом. В режиме 'or' оптимизатор захочет использовать один путь доступа, то есть индекс для таблицы Product. Поскольку ни один из приведенных выше индексов не может использоваться индивидуально, он возвращается к сканированию таблицы продукта. Если вы создаете индекс на (Ref1, Ref2), это все еще проблематично для поиска в Ref2. Он использует индекс, но накладывает на него дорогостоящую катушку. Я обновил запрос. – muhmud