NewID() Vs NewsequentialID() en claves primarias


 

En algunas situaciones nos puede tocar utilizar alguna clave artificial del tipo GUID como PK (Primary Key). Si bien esto en principio no es ningún problema, lo que sucede es que por defecto (a menos que nosotros digamos otra cosa) toda PK es el índice Clustered de la tabla y aquí si ya empezamos a tener problemas con este tipo de datos.

Dependiendo de la función que usemos podemos obtener mejores en la performance general de la tabla o bien condenarla a que si la PK es el clustered la misma pierda performance en las operaciones de Insert y además quede fragmentada.

Del lado de SQL Server existen dos funciones para poder hacer GUID las cuales son:   NEWID() y NEWSEQUENTIALID()

La primera genera GUID de forma aleatoria con lo cual el problema que vamos a tener que no son secuenciales y si esto lo ponemos en un índice Clustered vamos a tener una tabla mas fragmentada y con perdida de performance.

Ahora haremos algunas pruebas con código para poder comparar ambas funciones:

Creamos tablas:

Vamos a crear dos tablas con el tipo de dato Uniqueidentifier donde usaremos en un caso NEWID() y en otro NEWSEQUENTIALID().

Insertamos 300K registros a cada tabla:

Luego de hacer un INSERT de 300.000 registros a cada tabla haremos la siguiente consulta en cada tabla para observar que sucedió con el orden de las inserciones.

 

image

Aquí podemos observar que NEWID() (el segundo cuadro) fueron insertados de forma totalmente aleatoria impactando en la performance de esta tabla ya que sus PK son clustered.

Tiempos de inserción:

El siguiente grafico muestra el tiempo insumido en hacer los 300k Insert en cada caso.

image

Análisis de fragmentación:

Lo que analizaremos ahora es en que nivel de fragmentación han quedado cada una de las tablas y cual seria su impacto.

Para ello usaremos el siguiente query:

image

Aquí podemos observar que la tabla que ha usado NEWID tiene un 99% de fragmentación Triste.

Como podemos medir que impacto podría tener esto? para ello vamos a correr estas dos consultas y ver su consumo de reads.

Table ‘T_NEWSEQUENTIALID’. Scan count 1, logical reads 2266, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘T_NEWID’. Scan count 1, logical reads 3342, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Resumen:

Si necesitamos utilizar los campos GUID como PK lo ideal seria que no sean del tipo Clustered pero de serlo es ideal usar la función NEWSEQUENTIALID().

Debemos además mencionar que esta función tiene algoritmos mas performantes para poder calcular el GUID comparada contra  NEWID().