Ответ 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
секунды, а последний - мгновен.