序列与身份


87

SQL Server 2012Sequence作为一项新功能而引入,与Oracle和Postgres中的相同。序列优先于身份何处?为什么我们需要序列?


两者都使用后,我更喜欢使用Identity作为数据库中的全局用法。也就是说,您需要一个像ObjectID这样的自动递增数字,并希望在许多表中使用它。制作序列然后使用应用程序(网站或应用程序等)来管理基于序列号的插入和更新表会变得很复杂。
卷一

Answers:


81

我想你会在这里找到答案

使用一列的identity属性,您可以轻松生成自动递增的数字(通常用作主键)。使用Sequence,它将是一个不同的对象,您可以在插入时将其附加到表列。与身份不同,列值的下一个数字将从内存而不是从磁盘中检索-这使Sequence大大快于Identity。我们将在接下来的示例中看到这一点。

在这里

序列:序列已被SQL Server社区要求多年,并且已包含在此版本中。序列是用户定义的对象,它生成数字序列。这是使用序列的示例。

还有这里

SQL Server序列对象生成数字序列,就像sql表中的标识列一样。但是序列号的优点是序列号对象不限于单个sql表。

在msdn上,您还可以阅读有关用法以及我们为什么需要它的更多信息(此处):

序列是用户定义的模式绑定对象,该对象根据创建序列的规范生成数字值序列。数值序列按定义的时间间隔以升序或降序生成,并且可以按要求循环(重复)。与标识列不同,序列不与表关联。应用程序引用序列对象以接收其下一个值。序列和表之间的关系由应用程序控制。用户应用程序可以引用序列对象,并跨多个行和表协调值键。

使用CREATE SEQUENCE语句可独立于表创建序列。使用选项,您可以控制增量,最大值和最小值,起点,自动重启功能以及缓存以提高性能。有关选项的信息,请参见CREATE SEQUENCE。

与插入行时生成的标识列值不同,应用程序可以通过调用NEXT VALUE FOR函数在插入行之前获取下一个序列号。即使从未将序号插入表中,当调用NEXT VALUE FOR时也会分配序号。NEXT VALUE FOR函数可以用作表定义中列的默认值。使用sp_sequence_get_range一次获取多个序列号的范围。

序列可以定义为任何整数数据类型。如果未指定数据类型,则序列默认为bigint。


21

序列和标识都用于生成自动编号,但主要区别在于标识与表有关,而序列与表无关。

如果您需要全局维护一个自动编号(在多个表中),则还需要在特定编号之后重新启动间隔,并且还需要对其进行缓存以提高性能,这是我们需要顺序而不是顺序的地方身份。


14

尽管序列比标识列提供更大的灵活性,但我发现它们没有任何性能优势。

我发现使用身份的性能始终比使用批处理插入序列快3倍。

我插入了约150万行,性能为:

  • 14秒的身份
  • 序列45秒

我通过表默认值将行插入到使用序列对象的表中:

NEXT VALUE for <seq> for <col_name>

并尝试在select语句中指定序列值:

SELECT NEXT VALUE for <seq>, <other columns> from <table>

两者都是比同一方法慢的相同因素。我为序列使用了默认的缓存选项。

Arion第一个链接中引用的文章显示了逐行插入的性能,同一性和序列之间的差异对于10,000个插入为16.6秒至14.3秒。

高速缓存选项对性能有很大影响,但是对于较大的卷(+ 1M行),标识速度更快

请参阅此链接,以根据utly4life的评论进行深入分析。


序列的缓存大小是多少。
香农遣散费2014年

50,增加它的确有所作为,但我记得身份仍然更快。
Stagg 2014年

2
byobi.com/blog/2012/09/… 提供了各种配置的良好详细比较。显示缓存大小从50增加到500会产生大约2倍的速度差异。
ulty4life

您是否建议序列比身份列慢?我有相反的印象,因为序列是在内存中的,与从磁盘获取的身份不同。您的发现非常令人惊讶。很高兴与您分享。
RBT

1
通过使用序列,您可以通过alter sequence increment by ...简单地为新行腾出空间,然后使用base + row_number()或其他任何实际值来优化批处理插入性能。
哥迪

5

我知道这有点老了,但是想添加一个让我有些吃惊的观察。

我从身份切换到顺序,以按顺序排列索引。后来我发现序列不随复制转移。设置两个数据库之间的复制后,由于序列不同步,因此我开始收到密钥冲突。在您做出决定之前要提防的事情。


3

我发现序列的最佳用途不是替换标识列,而是创建“订单号”类型的字段。

换句话说,订单号向最终用户公开,并且可能具有业务规则。您希望它是唯一的,但仅使用标识列也不是正确的。

例如,不同的订单类型可能需要不同的顺序,因此与内部订单相比,您可能需要一个Internet订单序列。

换句话说,不要将序列视为标识的简单替代,而应将其视为在标识不符合业务要求的情况下有用。


1

最近,对于身份与序列,有一点需要考虑。似乎MSFT现在建议顺序,如果您想保持身份无间隙。我们遇到一个问题,即身份之间存在巨大差距,但是根据此声明,突出显示的内容可以解释我们的问题,即SQL缓存了身份,重新启动后我们丢失了这些数字。

https://docs.microsoft.com/zh-cn/sql/t-sql/statements/create-table-transact-sql-identity-property?view=sql-server-2017

服务器重新启动或其他故障后的连续值–由于性能原因,SQL Server可能会缓存标识值,并且在数据库故障或服务器重新启动期间某些分配的值可能会丢失。这可能导致插入时身份值出现空白。如果差距不可接受,则应用程序应使用自己的机制来生成键值。将序列生成器与NOCACHE选项一起使用可以将间隔限制为从未提交的事务。


1
有一个很好的答案可以解释为什么您跳过IDENTITY数字链接SEQUENCE具有与此处描述的链接相同的问题,但是您可以通过设置较小的CACHE大小来限制它,但是这需要在速度上进行权衡。
Mrphin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.