Перекрытие оболочки и отдельных индексов в SQL Server - PullRequest
3 голосов
/ 11 ноября 2010

У меня есть вопрос, касающийся рекомендаций по индексированию в SQL Server (или любой СУБД в этом отношении).Возьмем следующую таблицу:

ProfileID int
Text      nvarchar(50)

ProfileID присоединен к таблице Profile.Для каждого профиля каждый Text должен быть уникальным.Поэтому я поставил первичный ключ покрытия на обеих колонках.Отлично.

Однако я также хочу иметь возможность запросить приведенную выше таблицу по ProfileID.Поэтому я также поместил индекс и в ProfileID.

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

Изменить:

Я создал индекс в порядке (ProfileID, Text).Что если бы, ради аргумента, было 3 столбца A, B и C, которые имели индекс покрытия над всеми 3. Было бы полезно, если бы мы запросили «A» или «A, B и C», но не«В», или «С», или «В и С»?

1 Ответ

5 голосов
/ 11 ноября 2010

Индекс для (ProfileID, Text) (в этом порядке) также является индексом для ProfileID.

Вы все еще можете создать дополнительный индекс только для ProfileID, если хотите увеличить SELECT производительность по запросам, которые не включают Text.

Однако это имеет два недостатка:

  1. Для обслуживания двух индексов требуется больше ресурсов и производительность DMLзапросы (INSERT, UPDATE, DELETE) могут пострадать

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

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

Обложкаindex будет хэшем из двух столбцов (или я неправильно понимаю индексы покрытия)?

Действительно покрывающий индекс будет создан следующим образом:

CREATE INDEX ix_mytable_profile__text ON mytable (ProfileID) INCLUDE (Text)

Таким образом, Text будет храниться только в узлах конечного уровня индекса.

Однако, поскольку вы ниd UNIQUE index, оба столбца должны быть частью ключа.Узлы отсортированы лексикографически по ProfileID, затем Text.

Я создал индекс в заказе (ProfileID, Text).Что если бы, ради аргумента, было 3 столбца A, B и C, которые имели индекс покрытия над всеми 3. Было бы полезно, если бы мы запросили «A» или «A, B и C», но не"B", или "C", или "B and C"?

CREATE INDEX ix_mytable_a_b_c ON mytable (a, b, c)

SELECT  a, b, с
FROM    mytable
WHERE   a = 1 

-- Index lookup, no table lookup. a is leading

SELECT  a, b, с
FROM    mytable
WHERE   a = 1
        AND b = 1

-- Index lookup, no table lookup. (a, b) are leading.

SELECT  a, b, с
FROM    mytable
WHERE   b = 1

-- Index full scan (`b` is not leading), no table lookup

SELECT  a, b, с
FROM    mytable
WHERE   c = 1

-- Index full scan (`c` is not leading), no table lookup

SELECT  a, b, с, d
FROM    mytable
WHERE   a = 1

-- Index lookup, table tookup (d is not a part of the index).

SELECT  a, b, с, d
FROM    mytable
WHERE   b = 1

-- Table full scan (there is no point in using index at all, neither for lookup nor for covering).
...