¿Compartir una secuencia de clave primaria única en una base de datos?

14

¿Es una práctica aceptable usar una sola secuencia como clave primaria en todas las tablas (en lugar de que una clave primaria sea única para una tabla dada, es única para todas las tablas)? Si es así, ¿es objetivamente mejor que usar una sola secuencia de clave primaria en las tablas?

Soy un desarrollador de software junior, no un DBA, por lo que todavía estoy aprendiendo muchos de los conceptos básicos del buen diseño de bases de datos.

Editar: en caso de que alguien se pregunte, recientemente leí una crítica del diseño de una base de datos por parte de uno de los DBA de nuestra compañía que mencionó que era un problema que el diseño no usara una sola clave primaria en toda la base de datos, lo que sonaba diferente de lo que He aprendido hasta ahora.

Edit2: para responder una pregunta en los comentarios, esto es para Oracle 11g, pero me preguntaba en un nivel no específico de la base de datos. Si esta pregunta depende de la base de datos, me interesaría saber por qué, pero en ese caso estaría buscando una respuesta específica para Oracle.

Lawtonfogle
fuente
2
Por lo general, es una idea terrible, por razones de rendimiento.
Philᵀᴹ
1
En realidad, hay un beneficio más fuerte al tener cada tabla con su propio rango de clave primaria independiente. Pero solo en eso, cuando mira un grupo de ID, podría decir, esta es Cuentas, esa es PurchaseHeader, etc. Hacer esto requiere una configuración y (como cualquier cosa de propósito especial) un cuidado y alimentación continuos. (Sí, he trabajado con un sistema como este, hace muchos años.)
RLF
¿Qué DBMS estás usando? ¿Oráculo? Postgres? DB2?
a_horse_with_no_name
1
¿Es posible que hayas malinterpretado lo que quiso decir? ¿Quizás no estaba siendo tan literal?
JamesRyan
¿El DBA de la empresa realmente significa que no hay campos clave principales presentes en ninguna de las tablas?
Max Vernon

Respuestas:

13

¿Aceptable? Seguro. ¿Común? No. ¿Beneficioso? Dudoso.

En mi antiguo trabajo heredamos un sistema donde tenían un generador de secuencia central (este era un sistema SQL Server mucho antes de que SEQUENCEse introdujera en SQL Server 2012). No fue realmente un cuello de botella de rendimiento y no debería serlo a menos que esté generando cientos de miles de valores por segundo. Pero hizo que todo el código fuera mucho más complejo de lo que tenía que ser, sin ninguna buena razón. La intención del diseño era asegurarse de que si a algo en el sistema se le asignaba un valor de ID de 12, solo una cosa en el sistema podía tener la ID 12. Esto me pareció bastante obtuso y nunca lo entendí. Si tengo un cliente con CustomerID = 12, ¿por qué eso me impide tener un pedido con OrderID = 12?

Veo la utilidad de un generador de secuencia central si tiene múltiples sistemas y está generando ID para un determinado tipo de entidad (por ejemplo, un cliente o un pedido) a partir de estos múltiples sistemas. Una secuencia central puede repartir nuevos valores a múltiples sistemas sin ser un cuello de botella (solo un punto único de falla) y sin temor a que dos sistemas generen la misma ID.

Aaron Bertrand
fuente
Si tuviera que elegir entre algo como esto y simplemente usar identificadores únicos como claves principales, ¿tendría alguna preferencia (aunque la respuesta probablemente sea "depende")? Parece que un GUID solucionaría el problema de la misma manera, excepto que obtendría una implementación estándar en lugar de tener que rodar su propio generador de clave principal centralizado. Obviamente, usar una secuencia en SQL 2012 lograría ambas cosas, ¿pero suponiendo que alguien tenga una versión anterior?
SqlRyan
2
@SqlRyan Necesito entender por qué un OrderID debe ser completamente diferente de un CustomerID. Es casi seguro que no usaría un GUID para esto; La configuración de los rangos de IDENTIDAD podría ser mejor (los clientes comienzan en 1, los pedidos comienzan en 1000000, etc.) con alertas instaladas para cuando haya estado cerca de agotar el rango, por supuesto.
Aaron Bertrand
1
@SqlRyan: el uso de un GUID mal implementado como clave principal agrupada puede causar todo tipo de problemas. Como dijo Aaron, IDENTITY se ajusta mucho mejor al propósito.
Max Vernon
En un sistema anterior que he visto usando una sola secuencia en toda la base de datos, esto se hizo para permitir que una clave externa apunte a numerosas tablas diferentes en lugar de una sola tabla, de modo que cuando dijiste que la clave externa de dos filas diferentes eran 12, sabías que señalaban lo mismo sin necesidad de verificar a qué mesa posible apuntaban Un 13 en la misma columna podría ser la clave principal en una tabla diferente. Personalmente estoy muy incómodo con ese estilo de diseño.
Lawtonfogle
@AaronBertrand O, alternativamente, use identificadores enteros simples y agregue algún código al principio cuando estos estén orientados al cliente. p.ej. I1337, C1337 claramente una factura o cliente
JamesRyan
7

La idea tiene mérito en una base de datos muy compleja donde las personas podrían unirse accidentalmente a una tabla usando la columna incorrecta y obtener filas no válidas solo porque las ID INT son las mismas.

Elegimos tener GUID secuenciales como nuestras claves principales para evitar algunos de los escollos de fragmentación del índice de GUID. Lamentablemente son bastante grandes.

El servidor SQL puede generar GUID secuenciales a través de una invocación predeterminada de la función newSequentialID (), por lo que no hay una tabla de claves emitidas para mantener y ningún cuello de botella de bloqueo.

Esto nos ha proporcionado ID únicos en todas las bases de datos, en toda nuestra empresa, ya que son realmente únicos.

El precio, por supuesto, es el espacio y es problemático cuando intentas llevar los datos a un Data Warehouse / Cube donde la velocidad / tamaño se basa en el uso de teclas enteras más pequeñas.

Estoy convencido de que hemos evitado muchos errores en nuestra aplicación como resultado de su uso.

RayG
fuente
4

No puedo imaginar cuál podría ser la razón detrás de la secuencia única en todas las tablas. Todo lo que hace es crear un cuello de botella al generar nuevos valores.

No importa cuán pequeña sea la sobrecarga de generar valores de clave secuenciales, el generador es un único recurso, cuyo acceso debe sincronizarse. Cuantas más solicitudes reciba, mayores serán las posibilidades de que algunos solicitantes tengan que esperar su turno en el grifo. Es obvio que más clientes accederán al generador de secuencia única compartido entre todas las tablas con mayor frecuencia, produciendo así más contención que cualquiera de los múltiples generadores. La disputa puede volverse más pronunciada si las reglas comerciales imponen restricciones a los valores generados, como la ausencia de brechas o un orden estricto, o en una base de datos agrupada.

Incluso con el generador de secuencias más eficiente , habrá una carga de trabajo que causará contenciones intolerables.

mustaccio
fuente
2
Es posible que desee agregar detalles sobre cómo se crea el cuello de botella y por qué es una mala idea.
Max Vernon
2

El propósito de PrimaryKey en las tablas de la base de datos es principalmente hacer cumplir la unicidad de los datos que se supone que son únicos, porque no se pueden cubrir todos los flujos de trabajo y se garantiza que no se duplicarán los datos. La segunda razón es que muchas veces PK también es el candidato principal para el índice agrupado en la tabla, por lo que también aumenta la recuperación de datos cuando / donde estas columnas se usan correctamente en la consulta de selección.

el uso de un número de secuencia como clave primaria es igual a que cada tabla tiene una columna de identidad y solo esa columna se está utilizando en clave primaria. tener un número de secuencia único en la base de datos debe tener un uso específico, pero desde el punto de vista de PrimaryKey no entiendo la razón. Por ejemplo, en uno de los proyectos de Datawarehouse en el que trabajé, tenemos una columna llamada LoadBatchID y, desde ETL, hasta el 50% de la tabla tiene esta columna, pero en algunos lugares tiene un significado diferente. Utilizamos el proceso único como generador de números para asegurarnos de que no encontramos conflictos y también nos ayudan a rastrear el archivo original de donde provienen los datos y lo que sucede en cada una de las diferentes etapas de ETL.

Anup Shah
fuente
2

Supongo que una razón para hacerlo sería si todas las entidades heredaran de alguna entidad principal. Digamos, por ejemplo, que desea poder hacer un comentario sobre cualquier tipo de entidad:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Por lo general, esto no se hace. .

No sé sobre las características de rendimiento.

Neil McGuigan
fuente