Объявление индекса как уникального в SQL Server - PullRequest
21 голосов
/ 16 апреля 2009

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

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

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

Ответы [ 6 ]

26 голосов
/ 16 апреля 2009

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

См. Статью в моем блоге для подробного объяснения:


Теперь подробности кровавые.

Как сказал @ 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 на самом деле немного более эффективен, чем индекс 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 строк (id == uval == ival) первый запрос выполняется в течение 15 секунд, а второй - мгновенный.

4 голосов
/ 16 апреля 2009

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

1 голос
/ 15 апреля 2014

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

- без индекса:

    Setup Time: 8888, Insert Time: 501690

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

    Setup Time:   42, Insert Time: 488030

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

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

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

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

1 голос
/ 16 апреля 2009

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

0 голосов
/ 16 апреля 2009

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

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

0 голосов
/ 16 апреля 2009

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

...