如果我知道一个索引将具有唯一的值,那么如果我这样声明就会影响插入的性能,或选择它.
如果优化器知道索引是独一无二的,会影响查询计划?
我明白指定唯一性可以有助于保持诚信,但暂时将讨论放在一边,什么是性能后果.
解决方法
长篇小说:如果您的数据本质上是独一无二的,您将受益于在其上创建一个UNIQIE索引.
现在,血腥细节.
正如@Mehrdad所说,UNIQUENESS影响了计划构建器中的估计行数.
独特指数具有最大的可能选择性,这就是为什么:
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
如果优化器认为non_unique_indexed_field没有选择性,那么可能会受益于HASH JOIN.
如果你的索引是CLUSTERED(即它们自己被包含在索引叶中)和非UNIQUE,那么一个名为uniquifier的特殊隐藏列被添加到每个索引键中,从而使得键越大,索引越慢.
这就是为什么UNIQUE CLUSTERED指数实际上比非UNIQUE CLUSTERED指数更有效率.
在Oracle中,对于所谓的密钥保存需要对UNIQUE INDEX进行加入,这确保了表中的每一行最多被选中一次,并使视图更新.
这个查询:
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秒,后一个是即时.