Sequence - NO CACHE vs CACHE 1

25

Apakah ada perbedaan antara yang SEQUENCEdinyatakan menggunakan NO CACHEdan yang dinyatakan menggunakan CACHE 1di SQL Server 2012+?

Urutan # 1:

CREATE SEQUENCE dbo.MySeqCache1
AS INT
    START WITH 1
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 9999
    NO CYCLE
    CACHE 1;
GO

Urutan # 2:

CREATE SEQUENCE dbo.MySeqNoCache
AS INT
    START WITH 1
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 9999
    NO CYCLE
    NO CACHE;
GO

Apakah ada perbedaan di antara keduanya? Apakah mereka akan berperilaku berbeda ketika digunakan di lingkungan SQL Server 2012+?

marc_s
sumber

Jawaban:

24

Sulit untuk memberikan jawaban pasti atas pertanyaan ini sampai Anda benar-benar menemukan perbedaan. Saya tidak menemukan satu pun tapi itu tidak berarti tidak ada perbedaan hanya bahwa saya belum melihat satu pun dalam tes yang saya buat.

Tes mudah untuk kinerja. Entah mendapatkan nilai berikutnya dalam satu lingkaran atau menggunakan tabel angka sebagai sumber untuk menghasilkan beberapa nilai sekaligus. Dalam pengujian saya, tidak ada perbedaan dalam kinerja antara tidak menggunakan cache dan cache 1 nilai tetapi ada peningkatan kinerja yang signifikan menggunakan cache 2.

Ini adalah kode yang saya gunakan untuk menguji kinerja:

declare @D datetime = getdate();

declare @I int = 0;
while @I < 9999
  select @I = next value for dbo.S;

select datediff(millisecond, @D, getdate());

Hasil:

Cache        Time(ms)
------------ --------
NO CACHE     1200
1            1200
2             600
1000           70  

Untuk menggali sedikit lebih dalam, saya menggunakan event yang diperluas sqlserver.metadata_persist_last_value_for_sequencedan sqlserver.lock_acquireduntuk melihat apakah ada sesuatu yang berbeda dalam bagaimana nilai-nilai tetap ada pada tabel sistem.

Saya menggunakan kode ini untuk menguji tanpa cache dan ukuran cache 1 dan 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;

Tidak ada perbedaan dalam output untuk menggunakan tidak ada cache dan cache 1.

Output sampel:

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

Saat menggunakan cache 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

The SCH_Skunci dilakukan ketika nilai yang dibutuhkan. Dan ketika cache habis itu diikuti oleh a IXdan Ukunci dan akhirnya acara metadata_persist_last_value_for_sequencedipecat.

Jadi seharusnya tidak ada perbedaan antara menggunakan tidak ada cache dan dan cache 1 ketika datang ke berpotensi kehilangan nilai pada penutupan SQL Server yang tidak terduga.

Akhirnya saya melihat sesuatu di tab Pesan di SSMS saat membuat urutan dengan cache 1.

Ukuran cache untuk objek urutan 'dbo.S' telah diatur ke NO CACHE.

Jadi, SQL Server berpikir tidak ada perbedaan dan memberitahu saya begitu. Namun ada perbedaan di sys.sequencesdalam kolom cache_size. NULL tanpa cache dan 1 untuk cache 1.

Mikael Eriksson
sumber