web-dev-qa-db-ja.com

シーケンス-キャッシュなしvsキャッシュ1

SQL Server 2012+でNO CACHEを使用して宣言されたSEQUENCECACHE 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+環境で使用した場合、動作は異なりますか?

25
marc_s

実際に違いが見つかるまで、この質問に決定的な答えを出すことは困難です。私は何も見つけていませんが、行ったテストで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_sequencesqlserver.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ロックは、値が必要なときに行われます。そして、キャッシュが使い果たされると、その後にIXUロックが続き、最後にイベントmetadata_persist_last_value_for_sequenceが発生します。

したがって、SQL Serverの予期しないシャットダウンで値が失われる可能性がある場合、キャッシュを使用しない場合とキャッシュ1を使用する場合に違いはありません。

最後に、キャッシュ1でシーケンスを作成しているときに、SSMSの[メッセージ]タブに何かがありました。

シーケンスオブジェクト 'dbo.S'のキャッシュサイズはNO CACHEに設定されています。

したがって、SQL Serverは違いがないと判断し、違いを教えてくれます。ただし、sys.sequences列のcache_sizeには違いがあります。キャッシュがない場合はNULL、キャッシュが1の場合は1です。

24
Mikael Eriksson