Объявление индекса как уникального в SQL Server

Если я знаю, что индекс будет иметь уникальные значения, как это повлияет на производительность на вставках или выбирает, если я объявляю его как таковой.

Если оптимизатор знает, что индекс уникален, как это повлияет на план запроса?

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

Ответы

Ответ 1

Короче говоря: если ваши данные по существу UNIQUE, вам будет полезно создавать на них индекс UNIQIE.

Подробнее см. статью в своем блоге:


Теперь детали gory.

Как сказал @Mehrdad, UNIQUENESS влияет на подсчитанный счетчик строк в построителе плана.

UNIQUE индекс имеет максимально возможную селективность, поэтому:

SELECT  *
FROM    table1 t2, table2 t2
WHERE   t1.id = :myid
        AND t2.unique_indexed_field = t1.value

почти наверняка будет использовать NESTED LOOPS, а

SELECT  *
FROM    table1 t2, table2 t2
WHERE   t1.id = :myid
        AND t2.non_unique_indexed_field = t1.value

может выиграть от HASH JOIN, если оптимизатор считает, что non_unique_indexed_field не является выборочным.

Если ваш индекс CLUSTERED (т.е. сами строки содержатся в листьях индекса) и не UNIQUE, то к каждому индексному ключу добавляется специальный скрытый столбец с именем uniquifier, что делает ключ более крупным и индекс медленнее.

Вот почему индекс UNIQUE CLUSTERED на самом деле немного более эффективен, чем a non-UNIQUE CLUSTERED.

В Oracle требуется соединение на UNIQUE INDEX для такого имени key preservation, которое гарантирует, что каждая строка из таблицы будет выбрана не более одного раза и сделает просмотр обновляемым.

Этот запрос:

UPDATE  (
        SELECT  *
        FROM    mytable t1, mytable t2
        WHERE   t2.reference = t1.unique_indexed_field
        )
SET     value = other_value

будет работать в Oracle, а этот:

UPDATE  (
        SELECT  *
        FROM    mytable t1, mytable t2
        WHERE   t2.reference = t1.non_unique_indexed_field
        )
SET     value = other_value

не удастся.

Это не проблема с SQL Server.

Еще одна вещь: для таблицы, подобной этой,

CREATE TABLE t_indexer (id INT NOT NULL PRIMARY KEY, uval INT NOT NULL, ival INT NOT NULL)
CREATE UNIQUE INDEX ux_indexer_ux ON t_indexer (uval)
CREATE INDEX ix_indexer_ux ON t_indexer (ival)

этот запрос:

/* Sorts on the non-unique index first */
SELECT  TOP 1 *
FROM    t_indexer
ORDER BY
        ival, uval

будет использовать TOP N SORT, а этот:

/* Sorts on the unique index first */
SELECT  TOP 1 *
FROM    t_indexer
ORDER BY
        uval, ival

будет использовать только сканирование индекса.

Для последнего запроса нет необходимости в дополнительной сортировке на ival, так как uval являются уникальными в любом случае, и оптимизатор учитывает это.

В примере данных 200,000 rows (id == uval == ival) предыдущий запрос выполняется за 15 секунды, а последний - мгновен.

Ответ 2

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

Ответ 3

Производительность отрицательно влияет на вставку данных. Он должен проверить уникальность.

Ответ 4

Я только что проверил это на своей машине для таблицы Production, содержащей более 1 миллиона строк, потому что я решил, что это хороший тест. Результаты были интересными, здесь сырые числа:

- Нет индекса:

    Setup Time: 8888, Insert Time: 501690

- Уникальное ограничение:

    Setup Time:   42, Insert Time: 488030

Настройка состояла в получении Максимального поля, в которое я добавлял уникальное ограничение, - поэтому логически производительность была резко увеличена путем добавления ограничения. Это также улучшит производительность при поиске по этому внешнему ключу.

Интересно, что время вставки также немного улучшилось (на 2.7228%), поэтому только положительные воздействия [в моем тестовом примере] на добавление ограничения (+ встроенный индекс).

Тестирование показывает только положительное воздействие от добавления ограничения - не влияет на производительность.

ПРИМЕЧАНИЕ. Для нашей тестовой системы я ожидаю, что значения почти всегда будут уникальными, поэтому я не тестировал вставку неидеальных значений, в этих данных это действительно исключение - и не то, что нам нужно для выполнения.

Ответ 5

Да, он будет учитываться механизмом запросов.

Ответ 6

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

Производительность может быть затронута положительно или отрицательно или совсем не так: это будет зависеть от запроса, если индекс используется и т.д.