Hay dos tablas: Deal
y DealCategories
. Un acuerdo puede tener muchas categorías de acuerdos.
Entonces, la forma correcta debería ser hacer una tabla llamada DealCategories
con la siguiente estructura:
DealCategoryId (PK)
DealId (FK)
DealCategoryId (FK)
Sin embargo, nuestro equipo de subcontratación almacenó las múltiples categorías en la Deal
tabla de esta manera:
DealId (PK)
DealCategory -- In here they store multiple deal ids separated by commas like this: 18,25,32.
Siento que lo que hicieron está mal, pero no sé cómo explicar claramente por qué esto no está bien.
¿Cómo debería explicarles que esto está mal? ¿O tal vez soy yo quien está equivocado y esto es aceptable?
database-design
foreign-key
Sarawut Positwinyu
fuente
fuente
Respuestas:
Sí, es una idea terrible.
En lugar de ir:
Ahora tienes que ir:
Luego debe hacer cosas en el código de su aplicación para dividir esa lista de comas en números individuales, luego consultar la base de datos por separado:
Este diseño antipatrón se debe a un malentendido completo del modelado relacional (no tiene que tener miedo a las tablas. Las tablas son sus amigos. Úselos), o una creencia extrañamente equivocada de que es más rápido tomar una lista separada por comas y dividirla en el código de la aplicación de lo que es agregar una tabla de enlaces ( nunca lo es). La tercera opción es que no son lo suficientemente seguros / competentes con SQL para poder configurar claves externas, pero si ese es el caso, no deberían tener nada que ver con el diseño de un modelo relacional.
SQL Antipatterns (Karwin, 2010) dedica un capítulo entero a este antipatrón (que él llama 'Jaywalking'), páginas 15-23. Además, el autor ha publicado una pregunta similar en SO . Los puntos clave que observa (como se aplican a este ejemplo) son:
COUNT
,SUM
etc.), nuevamente, varían de 'complicadas' a 'casi imposibles'. Pregúnteles a sus desarrolladores cómo podrían obtener una lista de todas las categorías con un recuento del número de ofertas en esa categoría. Con un diseño adecuado, son cuatro líneas de SQL.VARCHAR
limitaciones de longitud de lista. Aunque si tienes una lista separada por comas que tiene más de 4000 caracteres, lo más probable es que el monstruo sea lento como el infierno de todos modos.TLDR: es un diseño fundamentalmente defectuoso, no se escalará bien, introduce una complejidad adicional incluso para las consultas más simples, y de forma inmediata ralentiza su aplicación.
fuente
En realidad, ese es un buen diseño si solo necesita consultar las categorías para un acuerdo determinado.
Pero es terrible si quieres conocer todas las ofertas en una categoría determinada.
Y también hace que sea realmente difícil y propenso a errores hacer cualquier otra cosa, como actualizaciones, recuentos, uniones, etc.
La desnormalización tiene su lugar, pero debe tener en cuenta que se optimiza para un tipo de consulta a expensas de todas las demás que pueda realizar con los mismos datos. Si sabe que siempre estará realizando consultas en un patrón, entonces podría darle una ventaja usar el diseño desnormalizado. Pero si hay alguna posibilidad de que pueda necesitar más flexibilidad en los tipos de consultas, quédese con un diseño normalizado.
Al igual que cualquier otra forma de optimización, necesita saber qué consultas va a ejecutar antes de poder decidir si la desnormalización está justificada.
fuente
select * from DealCategories where DealId in (1,2,3,4,...)
. Tiene más experiencia en el diseño de bases de datos que yo, por lo que tal vez tenga una buena razón en algunos casos para tal "ajuste extremo" en casos muy específicos. Mi única idea para justificar esto es unaselect
carga muy alta en Deal / DealCategory. Esto se parece mucho a un equipo externo sin ningún conocimiento de diseño de base de datos, más allá de crear tablas, lo creó.Múltiples valores en una columna están en contra de la primera forma normal.
Tampoco es absolutamente ninguna ganancia de velocidad, ya que las tablas deben vincularse en la base de datos. Primero debe leer y analizar una cadena, luego seleccionar todas las categorías para el "Acuerdo".
La implementación correcta sería una tabla de unión como "DealDealCategories", con DealId y DealCategoryId.
Mala implementación de la jerarquía?
Además, un FK en DealCategories a otra DealCategory parece una mala implementación de una jerarquía / árbol de DealCategories. ¡Trabajar con árboles a través de una relación de ID de padre (llamada lista de adyacencia) es un dolor!
Verifique los conjuntos anidados (buenos para leer, pero difíciles de modificar) y las tablas de cierre (el mejor rendimiento general, pero posiblemente un alto uso de memoria, ¡probablemente no demasiado para sus DealCategories) al implementar jerarquías!
fuente