2011-02-17 39 views
2

我想要尽可能高效地插入到数据库中,并且有大量不断传入的数据(每分钟大约10,000个,并且正在增长)。目前我正在使用准备好的插入语句,但我正在考虑使用SqlBulkCopy类以更大的块导入数据。快速插入;使用关系数据的BulkCopy

问题是我没有插入到单个表中 - 数据项的元素被插入到许多表中,并且他们的标识列被用作同时插入的其他行中的外键。我知道批量复制并不意味着允许更复杂的插入,但我想知道是否值得在uniqueidentifier列中交换我的身份列(在这种情况下是bigint)。这将允许我为每个表执行几个批量复制,并且由于我可以在插入之前确定ID,所以我不需要检查SCOPE_IDENTITY之类的任何内容,这些内容阻止我使用批量复制。

这听起来像是一个可行的解决方案,或者我可能会遇到其他潜在问题吗?或者,还有另一种方法可以快速插入数据,但保留使用bigint标识列吗?

谢谢。

回答

1

这听起来像是你正计划与“数据准备例程分配GUID代理键”方法交换“SQL分配一个[bigint身份()列]代用键”。换句话说,密钥不会在SQL中分配,而是从外部SQL分配。鉴于你的数量,如果数据生成过程可以分配代理键,我肯定会去。

问题就变成了,你必须使用GUID,还是数据生成过程可以产生自动递增整数?创建这样一个始终如一地运行的进程是很困难的(为什么你为SQL Server支付$ $$$的原因之一),但是在数据库中更小和更人性化的密钥的权衡可能是值得的。

+1

“创建这样一个可以持续且可靠工作的过程很难...”没错,但是如果你在数据库之外的一个单独的非共享应用程序中执行它,它会容易得多。没有争用,没有竞争条件,没有交易。 –

+0

我尝试了GUID,获得了10倍的性能(approp。10,000 inserts per second)。 :) – Barguast

3

uniqueidentifier可能会让事情变得更糟:页面分割和更宽。见this

如果你的负载/可以批量,一个选项是:

  • 加载一个临时表
  • 负载的实际表中一气呵成作为存储过程
  • 使用每个批次的临时表中的uniqueidentifier

我们处理每秒大约50k行的峰值(以这种方式增加)。实际上,我们使用单独的临时数据库来避免双重事务日志写入)

+0

我正在试验一个在C#中生成的顺序GUID(aka.COMB),我认为应该从链接中解决聚集索引问题。乍一看,我非常喜欢你的临时表想法,我假设这是为了存储具有GUID PKs的行,然后将它们转移到具有IDENTITY PK的表中。但是,这是否仍然需要执行大量的INSERT,因为我需要获取标识列?也许我是误解。 – Barguast

+1

@Bargauast:我们使用GUID来标识一个批处理(一些来自SQL BulkCopy,其他风险引擎也生成了一些)。然后我们用bigint聚集键将其刷入主表。GUID不是聚簇键,只是一种跟踪批量数据以清除主表的方法。 GUID仍然是16个字节宽,无论顺序与否,这加起来超过数十亿行。 – gbn