Sql – clave externa indirecta

Tengo algunas preguntas sobre el diseño de la base de datos.

  1. ¿Hay un nombre para esto?
  2. ¿Es una buena práctica?
  3. ¿Alguna consideración de rendimiento?

Tengo una estructura de tabla genérica utilizada para almacenar relaciones.

Recientemente refactoreé algunas cosas para usar esta estructura genérica en lugar de las columnas Fk directas, pero ahora no estoy seguro de si esa fue realmente la mejor idea.

Esquema original:


  + ------------------ + + --------------------- + + ------ ---------------- +
  |  Libro |  |  Nota |  |  MetaParent |
  | ------------------ |  | --------------------- |  | ---------------------- |
  |  Id |  |  Id |  |  Id |
  |  NoteId |  |  MetaParentId: (Nulo) |  |  MetaTableId |
  |  + ------- + + ---- + KeyValue |
  |  |  |  |  |  |
  |  |  |  |  |  |
  |  |  |  |  |  |
  |  |  |  |  |  |
  |  |  |  |  |  |
  + ------------------ + + --------------------- + + ------ ---------------- + 

Nuevo esquema


  + ------------------ + + --------------------- + + ------ ---------------- + |  Libro |  |  Nota |  |  MetaParent |  | ------------------ |  | --------------------- |  | ---------------------- |  |  Id |  |  Id |  |  Id |  |  |  |  MetaParentId: (Nulo) |  |  MetaTableId |  |  + + + ---- + KeyValue |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  + ------------------ + + --------------------- + + ------ ---------------- + 

Entonces, básicamente, en lugar de tener una relación Fk directa entre Libro y Nota, tenemos una relación indirecta a través de la tabla MetaParent usando las columnas MetaTableId / KeyValue.

Actualmente la tabla de MetaParent tiene aproximadamente 500k registros y las cosas se ejecutan aceptablemente. Pero reconstruimos los índices en él todas las noches.

Mi preocupación es que ahora la relación entre Libro y Nota no es obvia. Debes saber que existe uno y usar la tabla MetaParent.

Además del rendimiento, no estoy seguro en qué punto nos encontramos con problemas con las uniones contra MetaTableId / KeyValue demasiado lento. Parece que cuanto más agregue a esta tabla, más lentas serían las consultas.

Siempre debe hacer cumplir la integridad referencial mediante el uso de claves EXTRANJERAS “normales”.

En pocas palabras, las CLAVES EXTRAÑAS tienen las siguientes ventajas:

  1. Ya están implementados dentro del DBMS.
  2. Son declarativos , auto documentados y “obvios”.
  3. No se pueden omitir (a menos que se deshabilite o se elimine explícitamente).
  4. Ellos son correctos.
  5. Ellos son rápidos.
  6. Admiten acciones referenciales en cascada (como ON DELETE CASCADE).
  7. El DBMS sabe que los datos están relacionados, lo que le permite encontrar un mejor plan de consulta en algunos casos .
  8. Si está utilizando una herramienta ORM, puede generar automáticamente referencias entre objetos.

Y aquí están las desventajas correspondientes de imponer la integridad referencial en el código de la aplicación:

  1. Estás duplicando el trabajo que ya se ha realizado.
  2. Es imprescindible , probablemente “enterrado” en el código fuente de su aplicación, y más difícil de mantener.
  3. Una sola aplicación cliente que tiene un error puede romper la integridad referencial (y corromper los datos).
  4. Es probable que los implemente incorrectamente en el código de su aplicación. Parece simple desde el principio, pero en un entorno concurrente , es fácil introducir condiciones de carrera .
  5. Incluso si los ha implementado correctamente, probablemente haya utilizado alguna forma de locking para evitar condiciones de carrera, que es probable que sea más lenta / menos escalable que las FK especialmente optimizadas integradas en el DBMS.
  6. Tienes que implementar la cascada en ti mismo.
  7. El DBMS no sabe que los datos están relacionados, lo que puede producir un plan de consulta subóptimo.
  8. Es posible que necesite hacer más trabajo manual en su herramienta de ORM de su elección.

¿Hay un nombre para esto?

No que yo sepa. Escuché que se usa un término “FK generics”, pero probablemente no sea universal.

¿Es una buena práctica?

No (ver arriba).

¿Alguna consideración de rendimiento?

Sí (ver arriba).