Предложение where для некластеризованного индекса против дополнительного объединения и предложение where для кластеризованного индекса - PullRequest
2 голосов
/ 04 августа 2010

Я пытаюсь получить немного больше производительности от некоторых SQL-запросов, у которых есть предложение where для поля, которое является неуникальным некластеризованным индексом, это также внешний ключ в таблице A. Этот внешний ключпервичный ключ в таблице B и кластеризованный индекс.

Интересно, получу ли я выигрыш в производительности, если я добавлю объединение из таблицы A в таблицу B и получу предложение where в полечто такое кластеризованный индекс (в отличие от некластеризованного индекса без дополнительного объединения)?

спасибо

Ответы [ 5 ]

2 голосов
/ 04 августа 2010

Чтобы реально использовать этот дополнительный уровень производительности, лучше убедиться, что ваш неуникальный некластеризованный индекс представляет собой покрывающий индекс (т. Е. Индекс включает все столбцы, необходимые для удовлетворения запроса) для запроса, который вы выполняете. Вы можете воспользоваться концепцией включенных столбцов , введенной в SQL 2005, чтобы помочь вам сделать это.

1 голос
/ 04 августа 2010

Я сделал несколько тестов.У меня есть две таблицы - таблица A (~ 3000 строк) и таблица B (~ 200 строк).у них обоих есть идентификатор столбца.TableA: ID - pk, TableB: ID - fk, некластеризованный индекс.

Выберите из одной таблицы:

SELECT 
    a.ID
FROM
    dbo.TableA a
WHERE 
    a.ID IN (1,5,7,9,23,45,56,546,67,32,54,676)

- ПЛАН ИСПОЛНЕНИЯ:

|--Index Seek(OBJECT:([Database].[dbo].[TableA].[IX_TableA_ID] AS [a]), SEEK:([a].[ID]=(1) OR [a].[ID]=(5)) ORDERED FORWARD)

- СТАТИСТИКА IO:

Table 'TableA'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Выбор с использованием двух таблиц (внутреннее соединение)

SELECT 
    t.ID
FROM
    dbo.TableA a
INNER JOIN 
    dbo.TableB t  with(index(PK_TableBs)) ON t.ID = a.ID
WHERE 
    t.ID IN (1,5,7,9,23,45,56,546,67,32,54,676)

- ПЛАН ИСПОЛНЕНИЯ:

  |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[ID]))
       |--Clustered Index Seek(OBJECT:([Database].[dbo].[TableB].[PK_TableB] AS [t]), SEEK:([t].[ID]=(1) OR [t].[ID]=(5)) ORDERED FORWARD)
       |--Index Seek(OBJECT:([Database].[dbo].[TableA].[IX_TableA_ID] AS [a]), SEEK:([a].[ID]=[Database].[dbo].[TableB].[ID] as [t].[ID]),  WHERE:([Database].[dbo].[TableA].[ID] as [a].[ID]>=(1) AND [Database].[dbo].[TableA].[ID] as [a].[ID]<=(5)) ORDERED FORWARD)

- СТАТИСТИКА IO:

Table 'TableA'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TableB'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Результат:

Стоимость второго запроса составляет 67% (относительно пакета) по сравнению с первымзапрос (33%).Кроме того, второй запрос требует больше чтений.

PS.Это грязный быстрый пример, вы должны проверить свой.

0 голосов
/ 04 августа 2010

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

0 голосов
/ 04 августа 2010

Нет, согласно Фрэнку, для этого требуется больше чтений страниц из таблицы B. Вы говорите, что у вас уже есть индекс NC по внешнему ключу, по которому выполняется фильтрация.Вы также можете взглянуть на взвешивание плюсов и минусов кластеризации Таблицы A с помощью FK (ПК B) - если вы обычно всегда выбираете Таблицу A с помощью фильтрации по B, то это может уменьшить количество страниц, извлекаемых на A (но, очевидно,могут быть и другие запросы, на которые это может повлиять, и это может засчитаться)

0 голосов
/ 04 августа 2010

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

...