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+?
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.