Secuencia - NO CACHE vs CACHE 1


25

¿Hay alguna diferencia entre un SEQUENCEuso declarado NO CACHEy uno declarado CACHE 1en SQL Server 2012+?

Secuencia # 1:

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

Secuencia # 2:

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

¿Hay alguna diferencia entre los dos? ¿Se comportarán de manera diferente cuando se usen en un entorno SQL Server 2012+?

Respuestas:


24

Es difícil dar una respuesta definitiva a esta pregunta hasta que realmente encuentre una diferencia. No he encontrado ninguno, pero eso no significa que no haya diferencia solo que no he visto uno en las pruebas que he realizado.

La prueba fácil es para el rendimiento. Obteniendo el siguiente valor en un bucle o usando una tabla de números como fuente para generar múltiples valores a la vez. En mis pruebas no hubo diferencias en el rendimiento entre el uso de ningún caché y un valor de caché de 1, pero hubo una mejora significativa en el rendimiento del uso de un caché de 2.

Este es el código que usé para probar el rendimiento:

declare @D datetime = getdate();

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

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

Resultado:

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

Para profundizar un poco más, utilicé los eventos extendidos sqlserver.metadata_persist_last_value_for_sequencey sqlserver.lock_acquiredpara ver si había algo diferente en la forma en que los valores persisten en la tabla del sistema.

Usé este código para probar que no hay caché y el tamaño de caché de 1 y 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;

No hay diferencia en la salida para usar sin caché y caché de 1.

Salida de muestra:

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

Cuando se usa un caché 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

El SCH_Sbloqueo se realiza cuando se necesita un valor. Y cuando la memoria caché se agota, le sigue una IXy la Ucerradura y finalmente metadata_persist_last_value_for_sequencese dispara el evento .

Por lo tanto, no debería haber ninguna diferencia entre no usar caché y el caché 1 cuando se trata de perder valores potencialmente en un apagado inesperado de SQL Server.

Finalmente, noté algo en la pestaña Mensaje en SSMS al crear una secuencia con el caché 1.

El tamaño de caché para el objeto de secuencia 'dbo.S' se ha establecido en NO CACHE.

Entonces, SQL Server piensa que no hay diferencia y me lo dice. Sin embargo, hay una diferencia sys.sequencesen la columna cache_size. Es NULL para ningún caché y 1 para un caché de 1.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.