2010-02-03 23 views
92

Esta pregunta surge después de leer un comentario en esta pregunta:SQL - muchos-a-muchos tabla principal clave

Database Design

Cuando se crea una tabla de muchos a muchos, en caso de que crear una composición clave principal en las dos columnas de clave externa, o crear una clave primaria sustituta de "ID" de aumento automático, y simplemente poner índices en sus dos columnas FK (y tal vez una restricción única)? ¿Cuáles son las implicaciones en el rendimiento para insertar nuevos registros/volver a indexar en cada caso?

Básicamente, esto:

PartDevice 
---------- 
PartID (PK/FK) 
DeviceID (PK/FK) 

frente a esto:

PartDevice 
---------- 
ID (PK/auto-increment) 
PartID (FK) 
DeviceID (FK) 

El comentarista dice:

hacer las dos ID de la PK significa la mesa está ordenada físicamente en el disco en ese orden. Si insertamos (Part1/Device1), (Part1/Device2), (Part2/Device3), entonces (Parte 1/Dispositivo3) la base de datos tendrá que separar la tabla e insertar la última entre las entradas 2 y 3. Para muchos registros , esto se vuelve muy problemático ya que implica mezclar cientos, miles o millones de registros cada vez que se agrega uno. Por el contrario, un PK autoincrementing permite agregar los nuevos registros al final.

La razón por la que pido es porque siempre he sentido inclinado a hacer la clave principal compuesta con ninguna columna de incremento automático de alquiler, pero no estoy seguro de si la clave sustituta es en realidad con más prestaciones.

+0

gran pregunta, esperando algunas respuestas de sql guru :) – sbczk

+0

Aquí hay una pregunta silimar publicada en SO: http://stackoverflow.com/questions/344068/sql-server-clustered-index-order-of-index- pregunta – Tony

+0

(intenté agregar esto a mi comentario anterior pero no puedo) Dependiendo de la cantidad de insertos, también puede reconstruir periódicamente su índice para asegurarse de que devuelve resultados rápidamente. En SQL Server también puede modificar el FILLFACTOR del índice para proporcionar suficiente espacio para las inserciones antes de que tenga que mover los datos. – Tony

Respuesta

60

con un simple mapeo muchos-a-muchos de dos columnas, veo ninguna ventaja real para tener una clave sustituta. Tener una clave principal en (col1,col2) está garantizada como única (suponiendo que sus valores col1 y col2 en las tablas a las que se hace referencia son únicos) y un índice separado en (col2,col1) detectará aquellos casos en los que la orden contraria se ejecutará más rápido. El sustituto es una pérdida de espacio.

No necesitará índices en las columnas individuales ya que la tabla solo debe utilizarse para unir las dos tablas a las que se hace referencia.

Ese comentario al que hace referencia en la pregunta no vale los electrones que usa, en mi opinión. Parece que el autor cree que la tabla se almacena en una matriz en lugar de una estructura de árbol multidireccional equilibrada de alto rendimiento.

Para empezar, nunca es necesario almacenar u obtener en la tabla ordenado, solo el índice. Y el índice no será almacenado secuencialmente, se almacenará de manera eficiente para poder ser recuperado rápidamente.

Además, la gran mayoría de las tablas de la base de datos se leen más con más frecuencia que las escritas. Eso hace que cualquier cosa que hagas en el lado selecto sea mucho más relevante que cualquier cosa en el lado de la inserción.

+0

El último punto no es una buena generalización: "la gran mayoría de las tablas de la base de datos se leen con mucha más frecuencia que las escritas". Encuentro muchos ejemplos de tablas asociativas que deben escribirse con mucha frecuencia, p. una tabla que vincula al cliente con el pedido. – Medorator

+4

@buffer, apoyaré ese comentario (técnicamente, es una generalización solo si digo "todas las tablas", "gran mayoría" se basa en la experiencia).También pensemos en su ejemplo, una orden se crea una vez (puede actualizarse ocasionalmente, pero es poco probable que cambie la información de clave/índice, más para afectar cosas como el estado de la orden. Sin embargo, esas actualizaciones y las selecciones tendrá que hacer para imprimir facturas o generar informes de gestión van a superar la inserción original. – paxdiablo

+0

Think Amazon: miles de pedidos creados cada hora. – Medorator

12

No se necesita una clave sustituta para las tablas de enlaces.

Una PK en (col1, col2) y otro índice único en (col2, col1) es todo lo que necesita

A menos que utilice un ORM que no pueden hacer frente y dicta su diseño DB para usted ...

Editar: Le respondí lo mismo aquí: SQL: Do you need an auto-incremental primary key for Many-Many tables?

+0

Gracias por el enlace ... interesante –

+3

Puede estar bien con un índice dups en col2 en lugar de un índice único en (col2, col1). La ventaja del índice de dos columnas es que permite escaneos de solo índice en col2 solo o en col1 y col2 (aunque el otro índice, on (col1, col2) también maneja el caso 'both'). La desventaja es el almacenamiento adicional necesario para la columna adicional. Esto generalmente no es significativo, por lo que el consejo no es nada horrible. Sin embargo, si col1 y col2 son grandes o de tamaños muy diferentes, puede ahorrarse algo de espacio sin perjudicar el rendimiento al elegir tener el segundo índice solo en la columna más corta. –

+0

@gbn: el segundo índice en (col2, col1) no necesita ser único, ¿verdad? – Medorator

4

La manera más breve y directa en que puedo responder a su pregunta es decir que habrá un impacto en el rendimiento si las dos tablas que está vinculando no tienen claves primarias secuenciales. Como indicó/citó, el índice de la tabla de enlaces se fragmentará o el DBMS trabajará más para insertar registros si la tabla de enlaces no tiene su propia clave primaria secuencial. Esta es la razón por la cual la mayoría de las personas coloca una clave principal de incremento secuencial en las tablas de enlaces.

8

Podría ser necesaria una clave primaria incremental si se hace referencia a la tabla. Puede haber detalles en la tabla de muchos a muchos que deben extraerse de otra tabla utilizando la clave primaria incremental.

por ejemplo

PartDevice 
---------- 
ID (PK/auto-increment) 
PartID (FK) 
DeviceID (FK) 
Other Details 

Es fácil tirar de la 'Otros detalles' usando PartDevice.ID como el FK. Por lo tanto, se necesita el uso de clave primaria incremental.

Cuestiones relacionadas