如果我知道索引将具有唯一值,那么如果我声明它,它将如何影响插入或选择的性能。
如果优化器知道索引是唯一的,那将如何影响查询计划?
我知道指定唯一性可以保持完整性,但暂时搁置讨论,性能后果是什么。
如果我知道索引将具有唯一值,那么如果我声明它,它将如何影响插入或选择的性能。
如果优化器知道索引是唯一的,那将如何影响查询计划?
我知道指定唯一性可以保持完整性,但暂时搁置讨论,性能后果是什么。
长话短说:如果您的数据本质上是UNIQUE
,您将从为UNIQIE
它们创建索引中受益。
详细解释见我博客中的文章:
现在,血腥的细节。
正如@Mehrdad所说,UNIQUENESS
会影响计划生成器中的估计行数。
UNIQUE
index 具有最大可能的选择性,这就是为什么:
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
几秒钟,而后一个查询是即时的。
当然,优化器会考虑唯一性。它会影响查询计划中的预期行数。
插入数据时性能会受到负面影响。它需要检查唯一性。
我刚刚在我的机器上测试了一个包含超过 100 万行的生产表,因为我认为这是一个很好的测试。结果很有趣,这是原始数字:
-- 无索引:
Setup Time: 8888, Insert Time: 501690
-- 唯一约束:
Setup Time: 42, Insert Time: 488030
设置包括获取我添加唯一约束的字段的最大值 - 因此从逻辑上讲,通过添加约束可以显着提高性能。当通过这个外键搜索时,这也将提高性能。
有趣的是,插入时间也略有改善(提高了 2.7228%),因此只有添加约束(+ 固有索引)的积极影响 [在我的测试用例中]。
测试仅显示添加约束的积极影响 - 没有性能影响。
注意:对于我们的测试系统,我希望这些值几乎总是唯一的,所以我没有测试插入非唯一值,在这个数据中它确实是一个例外 - 而不是我们需要高性能的东西。
是的,它会被查询引擎考虑在内。
也许更重要的是:唯一性将保护数据的完整性。性能将有理由忽略这一点。
性能可能会受到正面或负面影响或根本不受影响:这取决于查询,是否使用索引等