2

我有一个包含三列的表,基本的 SELECT 语句如下所示:

SELECT TOP 1000 [PatchHistoryId]
      ,CASE 
        WHEN [PatchName] LIKE N'1_%' THEN '1_aaa'
        WHEN [PatchName] LIKE N'2_%' THEN '2_bbb'
        WHEN [PatchName] LIKE N'3_%' THEN '3_ccc'
        WHEN [PatchName] LIKE N'4_%' THEN '4_ddd'
        WHEN [PatchName] LIKE N'5_%' THEN '5_eee'
        WHEN [PatchName] LIKE N'6_%' THEN '6_fff'
        WHEN [PatchName] LIKE N'7_%' THEN '7_ggg'
        WHEN [PatchName] LIKE N'8_%' THEN '8_hhh' END AS PatchName
      ,[CreatedDate]

FROM [PatchHistory]

结果如下所示:

PatchHistoryId | PatchName | CreatedDate

-------------------------------------------

1       1_aaa   2013-07-19 12:50:14.637
2       2_bbb   2013-07-19 12:50:16.570
1002    3_ccc   2013-07-26 08:53:33.557
1003    3_ccc   2013-07-26 08:55:38.600
2002    4_ddd   2013-07-29 11:32:28.320
2003    4_ddd   2013-07-29 11:35:02.123
2004    4_ddd   2013-07-29 14:24:36.297
3002    4_ddd   2013-08-01 09:24:01.537
4002    6_fff   2013-08-06 11:18:29.990
5002    7_ggg   2013-08-08 15:22:56.990
6002    8_hhh   2013-08-20 15:15:35.157
6003    8_hhh   2013-08-20 15:16:40.300
6004    8_hhh   2013-08-20 15:18:00.177
6005    8_hhh   2013-08-20 15:18:00.370
6006    8_hhh   2013-08-20 15:18:00.587
6007    8_hhh   2013-08-20 15:18:00.747
6008    8_hhh   2013-08-20 15:18:00.957
6009    8_hhh   2013-08-20 15:18:01.100
6010    8_hhh   2013-08-20 15:18:01.263
6011    6_fff   2013-08-20 15:18:17.300
6012    8_hhh   2013-08-20 15:28:30.373

现在,首先我发现标识值非常高,因为我知道我只插入值 20-30 次,没有删除行。假设这一点,最大身份值需要 < 100,但不是。

我注意到 1000-1003 范围内的身份属于一个日期,2000-2004 属于另一个日期,6000-6012 也是另一个日期,对我来说这很奇怪。

看来如果我明天插入数据,下一个身份不会是 6013,而是 7000,或者更大。

在这种情况下有什么技巧。

PS 在表格设计中,PatchHistoryIdint,Identity seed 为 1,Increment 为 1。

4

2 回答 2

6

由于与新序列功能相关的代码更改,出于性能原因,SQL 2012 中的标识分配已更改。标识值现在预先分配在 1,000(对于 int 列)或 10,000(对于 bigint 列)的块中。

如果实例停止(如在重新启动或故障转移中),未使用的预分配值将被丢弃(因为持久的“下一个”指针已设置为下一个块)。

此外,连续的身份值总是通过中止的交易丢失,但是由于您每天有 1,000 个块,我会假设您的实例每天重新启动是原因(如果您不这样做,那么您不应该这样做)有一个很好的理由)。

源链接,见 Michael Duhons 条目

于 2013-08-20T14:04:41.340 回答
1

正如前面的答案已经解释的那样,这是由于 SQL Server 2012 缓存标识值的方式,这些标识值在服务器重新启动期间会丢失。

如果这导致您出现问题,您可以通过使用序列而不是标识列并指定 NO CACHE 子句来解决此问题,然后您的列的默认值为 NEXT VALUE FOR sequence_name。

请记住,虽然这将有助于标识值的跳跃,但它会略微影响性能,但如果您在示例中给出的表格代表您实际执行的插入数量,那么它不应该太多一个问题。

于 2013-08-20T14:47:27.920 回答