Последовательность - нет кэша против кэша 1

25

Есть ли разница между SEQUENCEобъявленным использованием NO CACHEи объявленным использованием CACHE 1в SQL Server 2012+?

Последовательность № 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

Есть ли разница между этими двумя? Будут ли они вести себя по-разному при использовании в среде SQL Server 2012+?

marc_s
источник

Ответы:

24

Трудно дать однозначный ответ на этот вопрос, пока вы на самом деле не найдете разницу. Я не нашел ничего, но это не значит, что нет никакой разницы только в том, что я не видел ни одного в проведенных мною тестах.

Простой тест на производительность. Либо получить следующее значение в цикле, либо использовать таблицу чисел в качестве источника для создания нескольких значений одновременно. В моих тестах не было различий в производительности между отсутствием кэша и кэшем 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Блокировка делается , когда требуется значение. И когда кеш исчерпан, за ним следует a IXи a Ulock, и, наконец, событие metadata_persist_last_value_for_sequenceзапускается.

Таким образом, не должно быть никакой разницы между использованием без кеша и кеша 1, когда речь идет о возможной потере значений при неожиданном завершении работы SQL Server.

Наконец, я заметил что-то на вкладке «Сообщение» в SSMS при создании последовательности с кешем 1.

Размер кэша для объекта последовательности 'dbo.S' был установлен на NO CACHE.

Итак, SQL Server думает, что нет никакой разницы, и говорит мне об этом. Однако есть разница в sys.sequencesстолбце cache_size. Это NULL для кеша нет и 1 для кеша 1.

Микаэль Эрикссон
источник