唯一键如何帮助提高 SQL 查询性能?

She*_*ell 6 sql-server unique-constraint

假设我有一个包含一id列的表,并且我在插入和更新记录时手动维护唯一值,而不是在该列上创建唯一键(例如,通过对 id 列值使用日期和时间,例如 201505061648)。我没有在我的表中使用任何索引或键。那么,即使列的基数为 100%,当我select使用where子句执行查询时,它是否会影响查询性能id

select * from myTable where id=15
Run Code Online (Sandbox Code Playgroud)

我的意思是唯一约束有助于提高查询性能还是只是强制用户唯一地维护记录,以便 SQL 在唯一约束列上获得更高的选择性?

我对唯一约束和唯一索引了解不多。在这个问题上给出的答案有助于理解 UniqueIndex 和 UniqueKey 之间的区别。我想更多地了解唯一键以及它如何提高我的查询性能。

zgg*_*guy 13

由于您链接到的 Stack Overflow 帖子解释了如何使用唯一索引实现唯一键约束,因此出于实际目的,两者是相同的,因此我将跳过该部分并尝试解释唯一索引如何提高查询性能。

让我们坚持您的示例,其中 table namedmyTable有一个 name 列id,该列碰巧填充了唯一值,但该列上没有唯一索引。我们还假设该表有另一列,anotherCol

现在有人来了,并提出了一个查询,如

select * from myTable where id = 15
Run Code Online (Sandbox Code Playgroud)

优化器必须决定如何找到所有满足条件 id = 15 的行。 从统计中可以知道列中的值是唯一的(num distinct = num rows in the table),但是,这并没有提供有关 id = 15 的行在磁盘上物理位置的任何信息。所以,数据库别无选择,只能扫描整个表以找到匹配的行。一旦找到 id = 15 的第一行,它甚至不能停止,因为不能保证没有更多这样的行。

现在,我们在 column 上创建一个唯一索引id,并重复相同的查询。

现在情况完全不同了。优化器现在知道只有两种可能性:要么正好有一行满足条件,要么没有这样的行。因此,如果存在所需的行,只需要一个廉价的索引查找即可;如果没有这样的行,相同的索引查找将不会返回任何结果。因此,查询将运行得很快。

假设在 上还有一个(正常的、非唯一的)索引anotherCol,并且您发出如下查询

select * from myTable where id = 15 and anotherCol = 100
Run Code Online (Sandbox Code Playgroud)

优化器现在可以在使用 id 上的索引、anotherCol 上的索引和表扫描之间进行选择。它将选择最具选择性的方法,因为它需要最少的工作来获得结果 - 因此它将再次使用唯一索引。

通常,只要您的查询具有与 AND(一种常见情况)连接的 where 子句谓词,并且 where 子句中的任何列都具有唯一索引,优化器将选择该索引作为访问方法,并且查询将快跑。

唯一索引不会被使用的唯一情况是当它不能被使用时,例如当一个查询像

select * from myTable where id = 15 or val = 100
Run Code Online (Sandbox Code Playgroud)

发出。由于谓词之间的条件是 OR,因此我们可以快速找到 id = 15 的行这一事实并没有多大意义,因为我们仍然需要找到 val = 100 的其他行。如果 val 没有被索引,则表扫描将是唯一的解决方案(呈现唯一索引查找无用,因为无论如何表扫描都会拾取 id = 15 的行);由于 val 已编入索引,优化器可能会选择使用这两个索引来分别查找满足每个条件的行,然后连接结果。

希望这能让你更清楚一些。

  • +1,有一个小说明。在具有唯一索引的第一个示例中,查找并不是唯一必需的:因为查询中有其他字段,数据库还必须在唯一索引中找到记录后进行键查找以检索记录。除非唯一索引也是表的聚集索引,在这种情况下,数据将与索引一起存储。 (3认同)
  • 你是对的。我忽略了这一点,因为它对论证来说似乎并不那么重要。 (2认同)

Mic*_*een 5

在决定如何检索基于该列的行时,优化器能够使用该列是唯一的这一知识。它可能会产生一个不同的、更有效的执行计划,其中有唯一的约束,而不是没有它。如果没有唯一约束,优化器必须从在该列上创建的统计对象进行插值,这是执行计划问题的永久来源。

当然,为强制唯一约束而创建的索引也是性能改进的重要来源。