1

我们有一个具有以下架构的表:

CREATE TABLE Measurement (
  HubId bigint NOT NULL
  ,DeviceId bigint NOT NULL
  ,Timestamp datetime NOT NULL
  ,Value bigint NOT NULL
)

我们希望以每秒大约 100,000 条记录的速度将记录导入此表,这些记录将被拆分到多个并发连接中。我可以通过将表视为堆(即没有索引)并使用SqlBulkCopy. 每秒有 100,000 个独特的HubIdDeviceIdTimestamp递增的组合。Value是随时间累积的。

我们还需要每秒读取两个最近的(在这种情况下是最后一个和倒数第二个 - 插入总是按顺序排列)值GROUP BY HubId, DeviceId,但只针对生成的行的子集(用户感兴趣的行)最后两个值之间的实时差异。

此外,出于历史目的,我们需要将每 15 分钟一次的数据聚合成 15 分钟的切片。此数据基于前 15 分钟切片的最大值和当前 15 分钟切片的最大值进行聚合...这需要在整个数据集中发生,但可以拆分为多个连接以实现唯一性HubIdDeviceId组合。因为Value是累积的,所以这实际上是前一个和当前 15 分钟切片的最后一个值。

批量插入带有索引的表会导致升级为独占表锁。此外,如果不升级到独占表锁,我们似乎无法执行查询。

任何人都可以给我一些关于构建这个的最佳方式的指示吗?我正在用头撞墙,试图找出最好的方法......

谢谢,院长

4

1 回答 1

0

因此,在反复来回之后,我们稍微改变了我们的方法,以达到我们需要的吞吐量。事实证明,我们只关心它们存在的那一刻的 100,000 条记录/秒,它们用于更新一组不断滚动的聚合和实时值。

我们使用多个工作线程将 100,000 行批量插入到临时堆表中(因此使用 4 个工作线程,每个线程处理大约 25,000 行),然后将聚集索引应用于临时表。然后,我们将临时表中的数据直接合并到实时表和聚合表中,并删除临时表。在这里,我们使用 ROWLOCK 提示强制 SQL 采用 ROWLOCK 而不是 TABLOCK 或 PAGLOCK,这会导致工作线程之间的争用超出必要的程度。

此外,我们将内存中的数据结构更改为有损堆栈而不是队列。在我们的情况下,这是合适的,因为我们通常只关心最新的数据,并且可以删除较旧的数据。

我们将使用分区作为我们口袋里的王牌,但我们目前仅限于 SQL Server 标准版,因此我们现在无法将它部署到我们的开发机器之外。

干杯,院长

于 2012-09-07T15:28:16.160 回答