web-dev-qa-db-fra.com

Séquence - NO CACHE vs CACHE 1

Existe-t-il une différence entre un SEQUENCE déclaré à l'aide de NO CACHE et un déclaré en utilisant CACHE 1 dans SQL Server 2012+?

Séquence # 1:

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

Séquence n ° 2:

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

Y a-t-il une différence entre les deux? Se comporteront-ils différemment lorsqu'ils seront utilisés dans un environnement SQL Server 2012+?

25
marc_s

Il est difficile de donner une réponse définitive à cette question jusqu'à ce que vous trouviez réellement une différence. Je n'en ai trouvé aucun mais cela ne veut pas dire qu'il n'y a pas de différence seulement que je n'en ai pas vu dans les tests que j'ai faits.

Le test facile concerne les performances. Soit obtenir la prochaine valeur dans une boucle ou utiliser une table de nombres comme source pour générer plusieurs valeurs à la fois. Dans mes tests, il n'y avait aucune différence de performances entre l'utilisation d'aucun cache et un cache de 1 valeur, mais il y avait une amélioration significative des performances de l'utilisation d'un cache de 2.

Voici le code que j'ai utilisé pour tester les performances:

declare @D datetime = getdate();

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

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

Résultat:

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

Pour creuser un peu plus, j'ai utilisé les événements étendus sqlserver.metadata_persist_last_value_for_sequence et sqlserver.lock_acquired pour voir s'il y avait quelque chose de différent dans la façon dont les valeurs persistent dans la table système.

J'ai utilisé ce code pour tester l'absence de cache et la taille du cache de 1 et 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;

Il n'y a pas de différence de sortie pour l'utilisation d'aucun cache et d'un cache de 1.

Exemple de sortie:

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

Lorsque vous utilisez un cache de 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

Le SCH_S le verrouillage est effectué lorsqu'une valeur est requise. Et lorsque le cache est épuisé, il est suivi d'un IX et d'un a U verrou et enfin de l'événement metadata_persist_last_value_for_sequence est renvoyé.

Il ne devrait donc pas y avoir de différence entre l'utilisation du cache et le cache 1 lorsqu'il s'agit de potentiellement perdre des valeurs lors d'un arrêt inattendu de SQL Server.

Enfin, j'ai remarqué quelque chose dans l'onglet Message de SSMS lors de la création d'une séquence avec le cache 1.

La taille du cache pour l'objet séquence 'dbo.S' a été définie sur NO CACHE.

Donc, SQL Server pense qu'il n'y a pas de différence et me le dit. Il existe cependant une différence dans sys.sequences dans la colonne cache_size. Il est NULL pour aucun cache et 1 pour un cache de 1.

24
Mikael Eriksson