Sql 在数据仓库中使用标识或序列

Sql 在数据仓库中使用标识或序列,sql,sql-server,etl,data-warehouse,sql-server-2019,Sql,Sql Server,Etl,Data Warehouse,Sql Server 2019,我是数据仓库新手,所以我尝试遵循最佳实践,模仿Microsoft Demo DB中的一些实现细节,我注意到的一点是使用序列作为PK over Identity的默认值 我可以问一下,一般来说,在数据仓库中使用Sequence over Identity是否更可取,尤其是在ETL过程中,哪个更方便?序列比Identity列有更多的保证。特别是,对序列的每次调用都保证为序列生成下一个值 但是,标识列可能有间隙和其他不一致之处。这些都有记录 由于对序列的额外保证,我怀疑它们的速度较慢。特别是,我怀疑数

我是数据仓库新手,所以我尝试遵循最佳实践,模仿Microsoft Demo DB中的一些实现细节,我注意到的一点是使用序列作为PK over Identity的默认值


我可以问一下,一般来说,在数据仓库中使用Sequence over Identity是否更可取,尤其是在ETL过程中,哪个更方便?

序列比Identity列有更多的保证。特别是,对序列的每次调用都保证为序列生成下一个值

但是,标识列可能有间隙和其他不一致之处。这些都有记录

由于对序列的额外保证,我怀疑它们的速度较慢。特别是,我怀疑数据库不能批量预分配值。这意味着在多线程环境中,序列会对事务施加序列化,从而降低速度


通常,我看到标识用于标识表中的列。虽然可能有一个性能比较,但我还没有看到。但我怀疑序列在某些情况下会稍微慢一点。

序列比标识列有更多的保证。特别是,对序列的每次调用都保证为序列生成下一个值

但是,标识列可能有间隙和其他不一致之处。这些都有记录

由于对序列的额外保证,我怀疑它们的速度较慢。特别是,我怀疑数据库不能批量预分配值。这意味着在多线程环境中,序列会对事务施加序列化,从而降低速度

通常,我看到标识用于标识表中的列。虽然可能有一个性能比较,但我还没有看到。但我怀疑序列在某些情况下会稍微慢一点。

序列和标识都是为OLTP表设计的,以便在多会话环境中有效分配唯一密钥

需要认识到的重要一点是,在数据仓库环境中,通常有不同的设置,并且只有一个作业填充特定的表

在单用户环境中,您根本不需要上述功能,您可以简单地手动分配键,从maxid+1开始,每行递增一

数据仓库的一般规则是,您不应该搜索silver bullet推荐,而应该在onw测试中检查功能和性能

如果您对SQL Server标识与序列进行了一些研究,例如,或者您得到了各种各样的结果,部分倾向于前者,部分倾向于后者

因此,我的建议是使用手动分配的ID执行测试,也就是说,没有开销,只需获得预期的基线

而不是重复它的身份和顺序-比较和选择

SQL Server中的序列是后来添加的,基于Oracle序列,因此我不认为它会有一些基本问题

Oracle的经验告诉我们,您需要在序列中有一个足够大的缓存来支持有效的大容量插入

同时,标识也可以定义为,identity|CACHE={ON | OFF},因此再次尝试所有三种可能性sequence、identity、nothing,并选择最佳的一种。

序列和标识都是为OLTP表设计的,以便在多会话环境中有效分配唯一密钥

需要认识到的重要一点是,在数据仓库环境中,通常有不同的设置,并且只有一个作业填充特定的表

在单用户环境中,您根本不需要上述功能,您可以简单地手动分配键,从maxid+1开始,每行递增一

数据仓库的一般规则是,您不应该搜索silver bullet推荐,而应该在onw测试中检查功能和性能

如果您对SQL Server标识与序列进行了一些研究,例如,或者您得到了各种各样的结果,部分倾向于前者,部分倾向于后者

因此,我的建议是使用手动分配的ID执行测试,也就是说,没有开销,只需获得预期的基线

而不是重复它的身份和顺序-比较和选择

SQL Server中的序列是后来添加的,基于Oracle序列,因此我不认为它会有一些基本问题

Oracle的经验告诉我们,您需要在序列中有一个足够大的缓存来支持有效的大容量插入

同时,标识也可以定义为,identity_CACHE={ON | OFF},所以再次尝试所有三种可能性顺序、identity、nothing,然后选择最好的一种。

identity i 的作用域为单个表,是表定义DDL的一部分,在截断时重置。标识在表中是唯一的。每个表在配置时都有自己的标识值,不能跨表共享。一般情况下,SQL Server在表上进行插入时使用下一个值+

Sequence是第一类对象,作用域为数据库。当序列用于下一个值时,将使用下一个值

当您需要跨多个表存储一个个人可读的唯一标识符时,可以最有效地使用序列。例如,在不同表中存储票证类型的票务系统可以使用一个序列来确保没有票证收到相同的号码,而不管它存储在哪个表中,并且一个人可以合理地引用该号码而不是GUID

在数据仓库中,维度表需要表内唯一的行标识符。通常,OLTP主键是不够的,因为它可能会根据维度的类型在维度表中重复,并且您不想冒险为OLTP PK分配额外的上下文,因为这可能会在源数据更改时引起问题。维度行标识符应仅对与其关联的非度量事实列具有意义。事实列不会跨不同维度连接++

由于维度表标识符的范围仅限于维度表,因此标识键是理想的行标识符。它创建简单,存储紧凑,在维度之外毫无意义。您不会在报表上使用维度标识。真的,请不要做那个开发人员

+很少需要知道下一个值而不需要指定行。如果在赋值之前试图操纵标识值,则可能是一个危险信号


++维度视图可以合并不同的表以向OLAP多维数据集提供数据,在这种情况下,应该从基础数据生成一个持久的可重复键,通常是通过以规范化格式将字符串文字与每个表键连接起来。

标识的作用域为单个表,是表定义DDL的一部分,在截断时重置。标识在表中是唯一的。每个表在配置时都有自己的标识值,不能跨表共享。一般情况下,SQL Server在表上进行插入时使用下一个值+

Sequence是第一类对象,作用域为数据库。当序列用于下一个值时,将使用下一个值

当您需要跨多个表存储一个个人可读的唯一标识符时,可以最有效地使用序列。例如,在不同表中存储票证类型的票务系统可以使用一个序列来确保没有票证收到相同的号码,而不管它存储在哪个表中,并且一个人可以合理地引用该号码而不是GUID

在数据仓库中,维度表需要表内唯一的行标识符。通常,OLTP主键是不够的,因为它可能会根据维度的类型在维度表中重复,并且您不想冒险为OLTP PK分配额外的上下文,因为这可能会在源数据更改时引起问题。维度行标识符应仅对与其关联的非度量事实列具有意义。事实列不会跨不同维度连接++

由于维度表标识符的范围仅限于维度表,因此标识键是理想的行标识符。它创建简单,存储紧凑,在维度之外毫无意义。您不会在报表上使用维度标识。真的,请不要做那个开发人员

+很少需要知道下一个值而不需要指定行。如果在赋值之前试图操纵标识值,则可能是一个危险信号


++维度视图可能会合并不同的表以提供OLAP多维数据集,在这种情况下,应该从基础数据生成一个持久的可重复键,通常是通过将字符串文字与每个表键以规范化格式连接起来。

请问在这种情况下,“保证”是什么意思?如果我理解正确,那么您更喜欢在数据仓库中使用标识而不是序列?@AnynameDonotcare。我的理解是,序列总是保证返回下一个值,没有间隙或重复。标识列没有这种保证,因此可能具有更好的性能。是的,我更喜欢大表的标识。序列也会产生间隙,否则它可能会被恶意用户滥用,在获得nextval后,在没有提交的情况下使用lanch,让所有其他用户等待,直到他准备好@GordonLinoff,但描述了缓存管理和引擎异常停止时可能存在的间隙?唯一的保证是明确的
声明是,除非使用循环,否则不会再次发布相同的值。@MarmiteBomber我可以问一下,在这种情况下,“担保”是什么意思吗?如果我理解正确,那么您更喜欢在数据仓库中使用标识而不是序列?@AnynameDonotcare。我的理解是,序列总是保证返回下一个值,没有间隙或重复。标识列没有这种保证,因此可能具有更好的性能。是的,我更喜欢大表的标识。序列也会产生间隙,否则它可能会被恶意用户滥用,在获得nextval后,在没有提交的情况下使用lanch,让所有其他用户等待,直到他准备好@GordonLinoff,但描述了缓存管理和引擎异常停止时可能存在的间隙?唯一明确声明的保证是,除非使用循环,否则不会再次发出相同的值。@MarmiteBomber