sql - tabla - Claves primarias compuestas: es bueno o malo
tabla compuesta sql server (4)
El espacio en disco es barato, por lo que una clave principal agrupada en una identidad int (1,1) nombrada después de una convención (como pk + nombre de la tabla) es una buena práctica. Hará que las consultas, las uniones, los índices y otras restricciones sean fáciles de administrar.
Sin embargo, hay una buena razón para no hacer eso (en MS SQL Server al menos): si desea administrar la clasificación física de sus datos en el sistema de almacenamiento subyacente.
La clave principal agrupada determina el orden físico de clasificación. Si lo hace en una columna de identidad, el orden de clasificación física es básicamente el orden de inserción. Sin embargo, esto puede no ser el mejor, especialmente si siempre consulta la tabla de la misma manera. En tablas muy grandes, obtener el orden de clasificación físico correcto hace que las consultas sean mucho más rápidas. Por ejemplo, puede querer el índice agrupado en un compuesto de dos columnas.
He estado diseñando una base de datos para un sistema de tienda en línea. La pregunta que me he encontrado al leer algunas publicaciones en este sitio web es que, aunque puedo usar claves primarias compuestas en el caso que explicaré a continuación, ¿es realmente una mala práctica (de acuerdo con los mensajes que leí al respecto? en stackoveflow, muchos dicen que es una mala práctica y por eso estoy preguntando).
Quiero almacenar pagos para los pedidos en una tabla separada. La razón es que, una orden puede tener muchos elementos que se manejan en una tabla separada en forma de relación de muchos a muchos. Ahora, si no uso claves primarias compuestas para mi tabla de pagos, perderé mi PaymentID
único:
[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key--
Ahora, si OrderId
la Clave principal para el OrderId
, perderé mi relación uno a uno aquí, por lo que Many OrderIds can be associated to many PaymentIds
, y no quiero esto.
Esta es la razón por la cual las preguntas anteriores aquí han concluido (principalmente) que la clave compuesta es una mala idea. Entonces quiero aclarar esto por mí mismo; si es malo, ¿cuál es la mejor práctica?
Esta pregunta está peligrosamente cerca de pedir opiniones, lo que puede generar guerras religiosas. Como alguien que está muy predispuesto a tener claves primarias enteras TablenameId
en mis tablas (llamadas algo así como TablenameId
, no `Id), hay una situación en la que es opcional.
Creo que las otras respuestas abordan por qué quieres las claves primarias.
Una razón muy importante es para fines de referencia. En una base de datos relacional, cualquier entidad podría, en teoría, ser referenciada por otra entidad a través de relaciones de claves extranjeras. Para claves externas, definitivamente desea una columna para definir de forma única una fila. De lo contrario, tiene que tratar con varias columnas en diferentes tablas que se alinean entre sí. Esto es posible, pero engorroso.
La tabla a la que se refiere no es una tabla de "entidad", es una tabla de "unión". Es una construcción de base de datos relacional para manejar relaciones de muchos a muchos. Como en realidad no representa una entidad, no debería tener relaciones de claves externas. Por lo tanto, una clave primaria compuesta es razonable. Hay algunas situaciones, como cuando le preocupa el tamaño de la base de datos, donde incluso es deseable omitir una clave primaria artificial.
La mejor práctica siempre es sobre lo que sea mejor para su aplicación. No busques con dureza los "mejores enfoques" arbitrarios, o podrías terminar con una peor aplicación de todos modos.
Una clave compuesta en SQL obliga a que la combinación de claves incluidas sea única. Es probable que haya un aumento exponencial en la complejidad de cada clave incluida, lo que podría significar una degradación exponencial del rendimiento, dependiendo de qué tan buenas optimizaciones de rendimiento pudieron hacer los ingenieros de la base de datos. A medida que la mesa crezca, también se degradará en rendimiento más rápido con las teclas compuestas.
Sin embargo, una disminución exponencial del rendimiento puede ser un buen negocio. Siempre que su tabla no contenga millones de filas, la conveniencia de que la combinación de teclas sea siempre única podría estar justificada. Además, si tiene tablas con millones de filas, es probable que tenga peores problemas para pensar que si sus claves son compuestas o no.
Como con todas las decisiones técnicas, es un acto de equilibrio. ¿Vale la pena la degradación del rendimiento?
Otra solución, que es muy común, es usar una llamada clave sustituta, y luego aplicar una restricción de índice única en las claves que deben ser únicas en combinación. Esto hace que las búsquedas en la tabla sean menos complicadas ya que solo implica el uso de un índice normal.
No hay conclusión de que las claves primarias compuestas sean malas.
La mejor práctica es tener una columna o columnas que identifiquen una fila de manera única. Pero en algunas tablas, una sola columna no es suficiente por sí misma para identificar de forma única una fila.
SQL (y el modelo relacional) permite una clave primaria compuesta. Es una buena práctica en algunos casos. O, otra forma de verlo es que no es una mala práctica en todos los casos.
Algunas personas tienen la opinión de que cada tabla debe tener una columna entera que genere automáticamente valores únicos, y que debería servir como la clave principal. Algunas personas también afirman que esta columna de clave principal siempre debe llamarse id
. Pero esas son convenciones , no necesariamente mejores prácticas. Las convenciones tienen algún beneficio, porque simplifica ciertas decisiones. Pero las convenciones también son restrictivas.
Es posible que tenga un pedido con pagos múltiples porque algunas personas lo hacen en reserva , o tienen múltiples fuentes de pago (dos tarjetas de crédito, por ejemplo), o dos personas diferentes quieren pagar una parte del pedido (con frecuencia voy a un restaurante con un amigo, y cada uno paga nuestra propia comida, por lo que el personal procesa la mitad del pedido en cada una de nuestras tarjetas de crédito).
Diseñaría el sistema que describes de la siguiente manera:
Products : product_id (PK)
Orders : order_id (PK)
LineItems : product_id is (FK) to Products
order_id is (FK) to Orders
(product_id, order_id) is (PK)
Payments : order_id (FK)
payment_id - ordinal for each order_id
(order_id, payment_id) is (PK)
Esto también está relacionado con el concepto de identificación de la relación . Si se trata de una definición de que un pago existe solo porque existe un pedido, entonces convierta el pedido en parte de la clave principal.
Tenga en cuenta que la tabla LineItems también carece de su propia clave primaria de autoincremento y columna única. Una tabla de muchos a muchos es un ejemplo clásico de un buen uso de una clave primaria compuesta.