GUID secuencial o bigint para la tabla de base de datos 'enorme' PK

14

Sé que este tipo de preguntas surgen mucho, pero aún no he leído ningún argumento convincente que me ayude a tomar esta decisión. ¡Por favor, tenga paciencia conmigo!

Tengo una gran base de datos: crece en aproximadamente 10,000,000 registros por día. Los datos son relacionales y, por razones de rendimiento, cargo la tabla con BULK COPY. Por esta razón, necesito generar claves para las filas, y no puedo confiar en una columna IDENTITY.

Un número entero de 64 bits, un bigint, es lo suficientemente ancho como para que lo use, pero para garantizar la unicidad, necesito un generador centralizado para hacer mis ID por mí. Actualmente tengo un servicio de generador que permite que un servicio reserve números de secuencia X y no garantiza colisiones. Sin embargo, una consecuencia de esto es que todos los servicios que tengo dependen de este generador centralizado, por lo que estoy limitado en cómo puedo distribuir mi sistema y no estoy contento con las otras dependencias (como requerir acceso a la red) impuestas por este diseño Esto ha sido un problema en ocasiones.

Ahora estoy considerando usar GUID secuenciales como mis claves principales (generadas externamente a SQL). Por lo que he podido determinar a partir de mis propias pruebas, el único inconveniente de estas es la sobrecarga de espacio en disco de un tipo de datos más amplio (que se ve exacerbado por su uso en los índices). No he presenciado ninguna desaceleración apreciable en el rendimiento de las consultas, en comparación con la alternativa bigint. Cargar la mesa con BULK COPY es un poco más lento, pero no mucho. Mis índices basados ​​en GUID no se fragmentan gracias a mi implementación secuencial de GUID.

Básicamente, lo que quiero saber es si hay otras consideraciones que pueda haber pasado por alto. Por el momento, me inclino a dar el salto y comenzar a usar GUID. De ninguna manera soy un experto en bases de datos, por lo que agradecería cualquier orientación.

Barguast
fuente
2
¿Cómo generarías un "GUID secuencial"?
Es una implementación personalizada. Básicamente es un formato de tipo GUID que tiene 6 bytes reemplazados por bytes de marca de tiempo y 2 bytes que representa un número de secuencia donde la marca de tiempo es la misma. No se garantiza que produzca valores secuenciales perfectos, pero es lo suficientemente bueno como para que la fragmentación del índice no sea un problema para mí.
¿Por lo tanto, está cargando estos datos desde múltiples fuentes diferentes? También supongo que el índice que le preocupa fragmentar es el índice agrupado.
2
Si va con un GUID secuencial, debe mirar NEWSEQUENTIALID (). Debería hacer lo que quiera (aumentando monotónicamente) y no se basa en un código personalizado.
2
Mire la publicación de Jeremiah Peschka en El problema con las claves. Buena lectura y se ha ocupado de esta implementación muchas veces.
billinkc

Respuestas:

4

Estoy en una situación similar. Actualmente, estoy usando el enfoque de GUID secuencial y no tengo fragmentación y generación de claves fácil.

He notado dos desventajas que me hicieron comenzar a migrar a bigint:

  1. El uso del espacio . 8 bytes más por índice. Multiplique eso por 10 índices más o menos y obtendrá una gran pérdida de espacio.
  2. Los índices del almacén de columnas no admiten GUID.

(2) Fue el asesino para mí.

Ahora generaré mis claves así:

yyMMddHH1234567890

Usaré una fecha inicial más una hora y tendré una parte secuencial después de eso. Eso me permite consultar en rango mis datos por fecha sin ningún índice de adición. Este es un buen bono para mí.

Generaré la parte secuencial del bigint usando un algoritmo HiLo que se presta bien para ser distribuido .

Espero que algo de esto se transfiera a su situación. Definitivamente recomiendo usar bigint.

usr
fuente
1
Marcar esto como la 'respuesta', ya que es la mejor opción (y parece apreciar lo que estoy preguntando y por qué esto no es tan sencillo como parece). Creo que voy a ir con un generador de secuencia compartida (que funcionará de manera similar a la sugerencia de su algoritmo HiLo). Tengo esto trabajando en otro sistema con pocos problemas, solo tendré que soportar la dependencia adicional. Oh bien. Gracias.
Barguast el
3

Con un tipo INT, comenzando en 1, obtienes más de 2 mil millones de filas posibles, que deberían ser más que suficientes para la gran mayoría de los casos. Con BIGINT, obtienes aproximadamente 922 cuatrillones (922 con 15 ceros - 922'000 billones) - ¿suficiente para ti?

Si usa un INT IDENTITYcomienzo en 1 e inserta una fila cada segundo, necesita 66.5 años antes de alcanzar el límite de 2 mil millones ...

Si usa un BIGINT IDENTITYcomienzo en 1 e inserta mil filas por segundo, necesita unos alucinantes 292 millones de años antes de alcanzar el límite de 922 billones ...

Usando sus 10 millones de filas por día, eso le llevará a tener suficientes números para aproximadamente 1'844'674'407'370 días ( 1844 mil millones de días o una marca de más de 5 mil millones de años ) de datos: es lo suficientemente bueno para sus necesidades ?

Lea más sobre esto (con todas las opciones que hay) en los Libros en línea de MSDN .

marc_s
fuente
1
La tasa de inserción de 10 millones de filas por día agotaría el rango INT en 200 días.
mceda
@mceda: sí, ¿reclamé algo más? Sin embargo, no agota el BIGINTrango tan rápido ...
marc_s
Gracias, pero como dije en mi pregunta, necesito los ID antes de enviarlos a la base de datos. Los datos son relacionales, por lo que necesito asignar claves primarias y externas antes de que se copien en masa. Si no fuera por eso, una IDENTIDAD BIGINT probablemente sería perfecta.
2
@Barguast: ¿no podría simplemente insertar en masa sus datos en una tabla de ensayo (sin la identidad) y luego moverlos desde allí a sus tablas de datos reales usando BIGINT IDENTITY?
marc_s
@marc_s: sí, el cálculo proporcionado no estaba alineado con la pregunta: "Si utiliza una IDENTIDAD INT que comienza en 1 e inserta una fila cada segundo, necesita 66.5 años antes de alcanzar el límite de 2 mil millones".
mceda
2

Le recomiendo que use SECUENCIA de tipo de datos BIGINT en SQL 2012. Esto es mucho más flexible que IDENTIDAD con opciones como caché / no caché, también puede asignar un rango de secuencia para su operación por lotes como sp_sequence_get_range.


fuente
Desafortunadamente, SEQUENCE no es compatible con Sql Azure.
Timothy Lee Russell
2

¿Es la razón por la que no puede usar IDENTITY porque ya hay relaciones de clave externa entre tablas separadas que está cargando? ¿Y no hay otra clave natural para que pueda vincularlos en una operación desde un área de preparación al área de producción? Por esa razón, me gustaría saber un poco más sobre cómo están actualmente "vinculados" en el sistema de origen antes de realizar una copia masiva. ¿Los sistemas de múltiples fuentes simplemente usan sus propias secuencias y tienen la posibilidad de secuencias conflictivas cuando se llevan a una base de datos compartida?

La técnica COMID ID / GUID secuencial es una con la que estoy familiarizado, y es factible cada vez que realmente necesita esa singularidad global asignada fuera de la base de datos: es efectivamente una identidad de fila utilizable tanto dentro como fuera de la base de datos. Por esa razón, en entornos altamente distribuidos o escenarios desconectados, es una buena opción

Excepto si realmente no lo necesita, porque esa diferencia de ancho adicional es significativa cuando aumenta el tamaño de los datos y estas claves están en cada índice y en los conjuntos de trabajo para muchas consultas.

Además, con la generación distribuida, si las filas en realidad no están en el orden de la columna GUID, los problemas con el uso de esto para la clave de índice agrupada (estrecha, estática, creciente) pueden causar cierta fragmentación en comparación con la agrupación en una IDENTIDAD permanecer.

Cade Roux
fuente
0

En general, es posible utilizar una OUTPUTcláusula de INSERTcomando para insertar datos en ambas tablas y relacionarlos con el campo de identidad.

El identificador que se basa en la marca de tiempo no debe considerarse confiable, depende del reloj del sistema, que a su vez depende de muchas cosas, desde el reloj de hardware hasta los servicios de sincronización de tiempo.

Serg
fuente