SQL Server 2012+でNO CACHE
を使用して宣言されたSEQUENCE
とCACHE 1
を使用して宣言されたものに違いはありますか?
シーケンス#1:
CREATE SEQUENCE dbo.MySeqCache1
AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9999
NO CYCLE
CACHE 1;
GO
シーケンス#2:
CREATE SEQUENCE dbo.MySeqNoCache
AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9999
NO CYCLE
NO CACHE;
GO
2つの間に違いはありますか? SQL Server 2012+環境で使用した場合、動作は異なりますか?
実際に違いが見つかるまで、この質問に決定的な答えを出すことは困難です。私は何も見つけていませんが、行ったテストで1つも見たことがないというだけの違いはありません。
簡単なテストはパフォーマンスです。ループで次の値を取得するか、数値テーブルをソースとして使用して一度に複数の値を生成します。私のテストでは、キャッシュを使用しない場合と値1のキャッシュを使用した場合でパフォーマンスに違いはありませんでしたが、キャッシュ2を使用した場合のパフォーマンスは大幅に向上しました。
これは、パフォーマンスのテストに使用したコードです。
declare @D datetime = getdate();
declare @I int = 0;
while @I < 9999
select @I = next value for dbo.S;
select datediff(millisecond, @D, getdate());
結果:
Cache Time(ms)
------------ --------
NO CACHE 1200
1 1200
2 600
1000 70
もう少し掘り下げるには、拡張イベントsqlserver.metadata_persist_last_value_for_sequence
とsqlserver.lock_acquired
を使用して、値がシステムテーブルに永続化する方法に何か違いがあるかどうかを確認しました。
このコードを使用して、キャッシュがないこと、およびキャッシュサイズが1と4であるかどうかをテストしました。
DECLARE @S NVARCHAR(max) = '
CREATE EVENT SESSION SeqCache ON SERVER
ADD EVENT sqlserver.lock_acquired(
WHERE (sqlserver.session_id=({SESSIONID}))),
ADD EVENT sqlserver.metadata_persist_last_value_for_sequence(
WHERE (sqlserver.session_id=({SESSIONID})))
ADD TARGET package0.event_file(SET filename=N''d:\SeqCache'');';
SET @S = REPLACE(@S, '{SESSIONID}', CAST(@@SPID AS NVARCHAR(max)));
EXEC (@S);
GO
CREATE SEQUENCE dbo.S
AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9999
NO CYCLE
NO CACHE;
-- CACHE 1;
-- CACHE 4;
GO
ALTER EVENT SESSION SeqCache ON SERVER STATE = START;
GO
DECLARE @I INT = 0;
WHILE @I < 10
SELECT @I = NEXT VALUE FOR dbo.S;
GO
ALTER EVENT SESSION SeqCache ON SERVER STATE = STOP;
DROP EVENT SESSION SeqCache ON SERVER;
DROP SEQUENCE dbo.S;
キャッシュなしと1のキャッシュを使用しても、出力に違いはありません。
出力例:
name persisted_value mode
----------------------------------------- --------------- -----
lock_acquired NULL SCH_S
lock_acquired NULL IX
lock_acquired NULL U
metadata_persist_last_value_for_sequence 1 NULL
lock_acquired NULL SCH_S
lock_acquired NULL IX
lock_acquired NULL U
metadata_persist_last_value_for_sequence 2 NULL
lock_acquired NULL SCH_S
lock_acquired NULL IX
lock_acquired NULL U
metadata_persist_last_value_for_sequence 3 NULL
4のキャッシュを使用する場合。
name persisted_value mode
----------------------------------------- --------------- -----
lock_acquired NULL SCH_S
lock_acquired NULL IX
lock_acquired NULL U
metadata_persist_last_value_for_sequence 4 NULL
lock_acquired NULL SCH_S
lock_acquired NULL SCH_S
lock_acquired NULL SCH_S
lock_acquired NULL SCH_S
lock_acquired NULL IX
lock_acquired NULL U
metadata_persist_last_value_for_sequence 8 NULL
SCH_S
ロックは、値が必要なときに行われます。そして、キャッシュが使い果たされると、その後にIX
とU
ロックが続き、最後にイベントmetadata_persist_last_value_for_sequence
が発生します。
したがって、SQL Serverの予期しないシャットダウンで値が失われる可能性がある場合、キャッシュを使用しない場合とキャッシュ1を使用する場合に違いはありません。
最後に、キャッシュ1でシーケンスを作成しているときに、SSMSの[メッセージ]タブに何かがありました。
シーケンスオブジェクト 'dbo.S'のキャッシュサイズはNO CACHEに設定されています。
したがって、SQL Serverは違いがないと判断し、違いを教えてくれます。ただし、sys.sequences
列のcache_size
には違いがあります。キャッシュがない場合はNULL、キャッシュが1の場合は1です。