sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cuáles son las mejores prácticas para usar un GUID como clave principal, específicamente con respecto al rendimiento?

Los GUID pueden parecer una opción natural para su clave principal, y si realmente debe hacerlo, probablemente podría argumentar para usarlo para la CLAVE PRINCIPAL de la tabla. Lo que recomiendo encarecidamente no hacer es usar la columna GUID como la clave de agrupación , que SQL Server hace de forma predeterminada, a menos que le indique específicamente que no lo haga.

Realmente necesita mantener dos cuestiones separadas:

  1. la clave principal es una construcción lógica, una de las claves candidatas que identifica de forma única y fiable cada fila de la tabla. Esto puede ser cualquier cosa, realmente - un INT , un GUID , una cadena:elija lo que tenga más sentido para su escenario.

  2. la clave de agrupación (la columna o columnas que definen el "índice agrupado" en la tabla):este es un físico algo relacionado con el almacenamiento, y aquí, un tipo de datos pequeño, estable y en constante aumento es su mejor elección:INT o BIGINT como su opción predeterminada.

De forma predeterminada, la clave principal en una tabla de SQL Server también se usa como clave de agrupación, ¡pero no tiene por qué ser así! Personalmente, he visto ganancias de rendimiento masivas al dividir la clave principal / agrupada basada en GUID anterior en dos claves separadas:la clave principal (lógica) en el GUID y la clave de agrupación (ordenación) en un INT IDENTITY(1,1) columna.

Como Kimberly Tripp, la reina de la indexación, y otros han dicho muchas veces, un GUID ya que la clave de agrupación no es óptima, ya que debido a su aleatoriedad, dará lugar a una fragmentación masiva de páginas e índices y, en general, a un mal rendimiento.

Sí, lo sé, hay newsequentialid() en SQL Server 2005 y versiones posteriores, pero incluso eso no es verdadera y completamente secuencial y, por lo tanto, también sufre los mismos problemas que el GUID - solo un poco menos prominente.

Luego, hay otro problema a considerar:la clave de agrupamiento en una tabla también se agregará a todas y cada una de las entradas en todos y cada uno de los índices no agrupados en su tabla; por lo tanto, realmente desea asegurarse de que sea lo más pequeño posible. Normalmente, un INT con más de 2 mil millones de filas debería ser suficiente para la gran mayoría de las tablas, y en comparación con un GUID como clave de agrupación, puede ahorrarse cientos de megabytes de almacenamiento en el disco y en la memoria del servidor.

Cálculo rápido - usando INT frente a GUID como clave principal y de agrupación:

  • Tabla base con 1 000 000 de filas (3,8 MB frente a 15,26 MB)
  • 6 índices no agrupados (22,89 MB frente a 91,55 MB)

TOTAL:25 MB frente a 106 MB - ¡y eso es solo en una sola mesa!

Un poco más de material para el pensamiento, excelente material de Kimberly Tripp, ¡léalo, léalo de nuevo, digiéralo! Es el evangelio de indexación de SQL Server, realmente.

  • GUID como PRIMARY KEY y/o clave agrupada
  • Continúa el debate sobre el índice agrupado
  • Clave de agrupación cada vez mayor:el debate sobre el índice agrupado..........¡otra vez!
  • El espacio en disco es barato - eso no el punto!

PD:por supuesto, si se trata de unos pocos cientos o miles de filas, la mayoría de estos argumentos no tendrán mucho impacto en usted. Sin embargo:si llega a las decenas o cientos de miles de filas, o comienza a contar en millones, entonces esos puntos se vuelven muy cruciales y muy importantes de entender.

Actualización: si quieres tener tu PKGUID columna como su clave principal (pero no su clave de agrupación), y otra columna MYINT (INT IDENTITY ) como su clave de agrupación:use esto:

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

Básicamente:solo tienes que explícitamente dile a la PRIMARY KEY restricción de que es NONCLUSTERED (de lo contrario, se crea como su índice agrupado, de forma predeterminada), y luego crea un segundo índice que se define como CLUSTERED

Esto funcionará, y es una opción válida si tiene un sistema existente que necesita ser "rediseñado" para el rendimiento. Para un sistema nuevo, si comienza desde cero y no se encuentra en un escenario de replicación, siempre elegiría ID INT IDENTITY(1,1) como mi clave principal agrupada, ¡mucho más eficiente que cualquier otra cosa!