Короче говоря: если ваши данные по сути 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
секунд, а второй - мгновенный.