SQL Server 2012Sequence
作为一项新功能引入,与 Oracle 和 Postgres 中的相同。序列在哪里比身份更受欢迎?为什么我们需要序列?
6 回答
我想你会在这里找到你的答案
使用列的标识属性,您可以轻松生成自动递增的数字(通常用作主键)。使用序列,它将是一个不同的对象,您可以在插入时附加到表列。与identity 不同,列值的下一个数字将从内存而不是磁盘中检索——这使得Sequence 比Identity 快得多。我们将在接下来的示例中看到这一点。
在这里:
序列:SQL Server 社区多年来一直在请求序列,它包含在此版本中。序列是一个用户定义的对象,它生成一个数字的序列。这是使用序列的示例。
以及这里:
SQL Server 序列对象生成数字序列,就像 sql 表中的标识列一样。但是序号的优点是序号对象不受单个sql表的限制。
在 msdn 上,您还可以阅读有关用法以及我们需要它的原因的更多信息(此处):
序列是用户定义的模式绑定对象,它根据创建序列的规范生成数值序列。数值序列以定义的时间间隔以升序或降序生成,并可按要求循环(重复)。与标识列不同,序列不与表关联。应用程序引用一个序列对象来接收它的下一个值。序列和表格之间的关系由应用程序控制。用户应用程序可以引用序列对象并跨多个行和表协调值键。
使用 CREATE SEQUENCE 语句独立于表创建序列。选项使您能够控制增量、最大值和最小值、起点、自动重新启动功能和缓存以提高性能。有关选项的信息,请参阅创建序列。
与插入行时生成的标识列值不同,应用程序可以在插入行之前通过调用 NEXT VALUE FOR 函数获取下一个序列号。在调用 NEXT VALUE FOR 时分配序列号,即使该编号从未插入到表中。NEXT VALUE FOR 函数可用作表定义中列的默认值。使用 sp_sequence_get_range 一次获取多个序列号的范围。
序列可以定义为任何整数数据类型。如果未指定数据类型,则序列默认为 bigint。
序列和标识都用于生成自动编号,但主要区别在于标识是依赖于表的,而序列独立于表。
如果您有一个需要全局维护自动编号的场景(在多个表中),您还需要在特定编号之后重新启动间隔并且您还需要缓存它以提高性能,这里是我们需要序列而不是身份。
尽管序列比标识列提供了更多的灵活性,但我没有发现它们有任何性能优势。
我发现使用标识的性能始终比使用序列进行批量插入快 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 的评论,请参阅此链接以进行深入分析。
我知道这有点老了,但想添加一个让我印象深刻的观察。
我从身份切换到序列以按顺序排列索引。后来我发现该序列不会随着复制而转移。由于序列不同步,我在两个数据库之间设置复制后开始出现密钥冲突。只是在你做出决定之前需要注意的事情。
我发现序列的最佳用途不是替换标识列,而是创建“订单号”类型的字段。
换句话说,订单号向最终用户公开,并且可能附带业务规则。您希望它是唯一的,但仅使用标识列也不是真正正确的。
例如,不同的订单类型可能需要不同的顺序,因此您可能有一个互联网订单的顺序,而不是内部订单。
换句话说,不要将序列视为身份的简单替代品,将其视为在身份不符合业务需求的情况下有用。
最近有点需要考虑身份与序列的问题。如果您可能想保持身份没有间隙,似乎 MSFT 现在建议序列。我们遇到了身份存在巨大差距的问题,但基于此突出显示的声明将解释我们的问题,即 SQL 缓存了身份,并且在重新启动后我们丢失了这些数字。
服务器重新启动或其他故障后的连续值 - SQL Server 可能出于性能原因缓存标识值,并且在数据库故障或服务器重新启动期间,某些分配的值可能会丢失。这可能会导致插入时标识值出现间隙。如果间隙不可接受,则应用程序应使用自己的机制来生成键值。使用带有 NOCACHE 选项的序列生成器可以将间隙限制为从未提交的事务。