ber*_*d_k 36 sql-server sequence sql-server-2012
在他对哪个更好的回答中:标识列还是生成的唯一 id 值?mrdenny 说:
当 SQL Denali 出现时,它将支持比身份更高效的序列,但您无法自己创建更高效的东西。
我不确定。知道 Oracle 的序列后,我要么为插入创建触发器,将每个插入封装到存储过程的调用中,要么祈祷我在执行临时插入时不要忘记正确使用序列。
我怀疑序列的优势是否如此明显。
mrd*_*nny 37
我也会在这里回答。它IDENTITY与SEQUENCE工作方式和工作的内部结构有关。
使用IDENTITY,SQL Server 将值预缓存到内存中,以便它们随时可用。有关详细信息,请参阅Martin Smith 的回答。使用值时,后台进程会生成更多值。可以想象,这个池会很快耗尽,让应用程序受制于生成值的后台进程。
使用SEQUENCE,SQL Server 允许您定义缓存应该有多大。虽然 SQL Server 实际上并不将值保留在缓存中,它只保留当前值和最高端值,这将大大减少创建值所需的 IO 量。
不要将缓存设置得太高,因为这会减少可以使用的数字数量:如果 SQL Server 崩溃,当前缓存范围中指定的任何未使用的值都将丢失。
至于行插入,只需为列指定一个默认值,如下所示:
DEFAULT (NEXT VALUE FOR Audit.EventCounter),
Run Code Online (Sandbox Code Playgroud)
Mar*_*ith 21
自从Itzik Ben Gan 的文章被写出来后,硬编码的缓存大小 10IDENTITY似乎已经改变了。来自对这个连接项目的评论
预分配的大小基于定义标识属性的列的数据类型的大小。对于 SQL Server 整数列,服务器预先分配 1000 个值范围内的标识。对于 bigint 数据类型,服务器预先分配 10000 个值的范围。
在T-SQL查询本书包含以下表,但强调的是,这些值不记录或保证是不变的。
+-----------------+-----------+
| DataType | CacheSize |
+-----------------+-----------+
| TinyInt | 10 |
| SmallInt | 100 |
| Int | 1,000 |
| BigInt, Numeric | 10,000 |
+-----------------+-----------+
Run Code Online (Sandbox Code Playgroud)
这里的文章测试了各种序列缓存大小和插入批次大小,并得出以下结果。

这似乎表明,对于大型插入IDENTITY,执行SEQUENCE. 但是,它不会测试缓存大小为 1,000,而且这些结果只是一项测试。专门查看缓存大小为 1,000 的各种批量大小的插入,我得到了以下结果(尝试每个批量大小 50 次并将结果汇总如下-所有时间都在 ?s 中。)
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| | Sequence | Identity |
| Batch Size | Min | Max | Avg | Min | Max | Avg |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| 10 | 2,994 | 7,004 | 4,002 | 3,001 | 7,005 | 4,022 |
| 100 | 3,997 | 5,005 | 4,218 | 4,001 | 5,010 | 4,238 |
| 1,000 | 6,001 | 19,013 | 7,221 | 5,982 | 8,006 | 6,709 |
| 10,000 | 26,999 | 33,022 | 28,645 | 24,015 | 34,022 | 26,114 |
| 100,000 | 189,126 | 293,340 | 205,968 | 165,109 | 234,156 | 173,391 |
| 1,000,000 | 2,208,952 | 2,344,689 | 2,269,297 | 2,058,377 | 2,191,465 | 2,098,552 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
Run Code Online (Sandbox Code Playgroud)
对于较大的批量大小,该IDENTITY版本似乎通常更快。
TSQL Querying 一书还解释了为什么IDENTITY比序列具有性能优势。
这IDENTITY是表特定的,SEQUENCE不是。如果灾难是在刷新日志缓冲区之前发生在插入中间,那么恢复的标识是否是较早的标识并不重要,因为恢复过程也会撤消插入,因此 SQL Server 不会强制刷新每个标识的日志缓冲区缓存相关的磁盘写入。但是,对于 Sequence,这是强制执行的,因为该值可能用于任何目的 - 包括在数据库之外。所以在上面的例子中,有一百万次插入和 1,000 的缓存大小,这是额外的一千次日志刷新。
DECLARE @Results TABLE(
BatchCounter INT,
NumRows INT,
SequenceTime BIGINT,
IdTime BIGINT);
DECLARE @NumRows INT = 10,
@BatchCounter INT;
WHILE @NumRows <= 1000000
BEGIN
SET @BatchCounter = 0;
WHILE @BatchCounter <= 50
BEGIN
--Do inserts using Sequence
DECLARE @SequenceTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_Seq1_cache_1000
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @SequenceTimeEnd DATETIME2(7) = SYSUTCDATETIME();
--Do inserts using IDENTITY
DECLARE @IdTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_identity
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @IdTimeEnd DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO @Results
SELECT @BatchCounter,
@NumRows,
DATEDIFF(MICROSECOND, @SequenceTimeStart, @SequenceTimeEnd) AS SequenceTime,
DATEDIFF(MICROSECOND, @IdTimeStart, @IdTimeEnd) AS IdTime;
TRUNCATE TABLE dbo.t1_identity;
TRUNCATE TABLE dbo.t1_Seq1_cache_1000;
SET @BatchCounter +=1;
END
SET @NumRows *= 10;
END
SELECT NumRows,
MIN(SequenceTime) AS MinSequenceTime,
MAX(SequenceTime) AS MaxSequenceTime,
AVG(SequenceTime) AS AvgSequenceTime,
MIN(IdTime) AS MinIdentityTime,
MAX(IdTime) AS MaxIdentityTime,
AVG(IdTime) AS AvgIdentityTime
FROM @Results
GROUP BY NumRows;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4003 次 |
| 最近记录: |