2010-10-25 17 views
22

Me preguntaba si tiene un sitio web con una docena de tipos diferentes de listados (Tiendas, Restaurantes, Clubes, Hoteles, Eventos) que requieren campos diferentes, ¿hay algún beneficio de crear una tabla con columnas define como tal
Ejemplo Shop:tabla fija única con columnas múltiples versus tablas abstractas flexibles

shop_id | name | X | Y | city | district | area | metro | station | address | phone | email | website | opening_hours 

O un enfoque más abstracto similar a esto:

object_id | name   
--------------- 
1   | Messy Joe's 
2   | Bate's Motel 

type_id | name 
--------------- 
1  | hotel 
2  | restaurant 


object_id | type_id 
--------------- 
1   | 2 
2   | 1 

field_id | name   | field_type 
--------------- 
1  | address  | text 
2  | opening_hours | date 
3  | speciality  | text 

type_id | field_id 
--------------- 
1  | 1 
1  | 2 
2  | 1 
2  | 3 

object_id | field_id | value 
1   | 1  | 1st street.... 
1   | 3  | English Cuisine 

Por supuesto que puede haber más abstracto si el valor son predefinidos (Ejemplo: especialidades coul d tiene su propia lista)

Si tomo el enfoque abstracto, puede ser muy flexible, pero las consultas serán más complejas con muchas combinaciones. Pero no sé si esto afecta el rendimiento al ejecutar estas consultas 'más complejas'.

Me interesaría saber cuáles son las ventajas y desventajas de ambos métodos. Puedo imaginarme por mí mismo, pero no tengo la experiencia para confirmar esto.

+2

Gracias. Puede que le interese ** esta [pregunta/respuesta] (http://stackoverflow.com/questions/4304217/database-schema-which-can-support-specialized-properties/4359193#4359193) ** también. – PerformanceDBA

Respuesta

71

Ciertas cuestiones deben aclararse y resolverse antes de podemos entrar en una discusión razonable.

Pre-requisitos de resolución de

  1. etiquetas
    En una profesión que exige precisión, es importante que usamos etiquetas precisas, para evitar confusiones, y por lo que nos podemos comunicar sin tener que utilizar descripciones prolíficas y calificadores.
    .
    Lo que ha publicado como FixedTables, es Unnormalised. Justo lo suficiente, puede tratarse de un intento en la forma Tercera Normal, pero de hecho es un archivo plano, no normalizado (no "denormalizado". Lo que ha publicado como AbstractTables es, para ser precisos, Entidad-Valor-Atributo, que es casi, pero no del todo, la forma normal sexto lugar, y es por lo tanto más normalizado que 3NF. Suponiendo que se haga correctamente, por supuesto.

    • El archivo plano desnormalizará no está "desnormalizaremos". se está lleno de duplicación (no se ha hecho nada para eliminar grupos repetitivos y columnas duplicadas o para resolver dependencias) y nulos, es un rendimiento alto de muchas maneras y evita la concurrencia.

    • Para ser Denormlaised, primero tiene que ser Normalizado, y luego la Normalización retrocedió un poco por alguna buena razón. Como no está Normalizado en primer lugar, no se puede desnormalizar. Simplemente no está normalizado.

    • No se puede decir que se denormaliza "para el rendimiento", porque ser un cerdo de rendimiento es la antítesis del rendimiento. Bueno, necesitan una justificación para la falta de diseño formal], y "para el rendimiento" es eso. Incluso el escrutinio formal más pequeño expuso la tergiversación (pero muy pocas personas pueden proporcionarlo, por lo que permanece oculto, hasta que obtienen un extraño para abordar, lo adivinaste, el problema del rendimiento masivo).

    • Las estructuras normalizadas funcionan mucho mejor que las estructuras no normalizadas. Las estructuras más normalizadas (EAV/6NF) funcionan mejor que las estructuras menos normalizadas (3NF/5NF).

    • estoy de acuerdo con la idea central de los potros de OMG, pero no sus etiquetas y definiciones

    • en lugar de decir 'no 'denormalise' a menos que tenga a', estoy diciendo, 'Normalizar fielmente, punto ' y ' si hay un problema de rendimiento, no se ha normalizado correctamente '.
      .
  2. Wiki
    Las entradas re Formas Normales y Normalización son una broma. Específicamente, las definiciones son incorrectas; confunden las Formas Normales; no tienen idea del proceso de Normalización; y otorgan el mismo peso a NF absurdas o cuestionables que han sido desacreditadas hace mucho tiempo. El resultado es que Wiki agrega a un tema ya confuso y raramente entendido. Así que no pierdas tu tiempo.
    .
    Sin embargo, para avanzar, sin que esa referencia represente un obstáculo, permítanme decir esto.

    • La definición de 3NF es estable, y no ha cambiado.
    • Existe una gran confusión entre los NF entre 3NF y 5NF. La verdad es que esta es un área que progresó en los últimos 15 años; y muchas organizaciones, académicos y proveedores con sus productos con limitaciones, saltaron a crear un nuevo "Formulario normal" para validar sus ofertas. Todos sirven intereses comerciales y académicamente poco sólidos. 3NF en su estado original no templado pretendía y garantizaba ciertos atributos.
    • La suma total es, 5NF es hoy, lo que 3NF estaba destinado a ser hace 15 años, y puede omitir la broma comercial y los doce o más NF "especiales" (comerciales y pseudoacadémicas) intermedios, algunos de los cuales están identificados en Wiki, e incluso eso en términos confusos.
      .
  3. Como ha podido comprender e implementar el EAV en su publicación, no tendrá problemas para comprender lo siguiente. Por supuesto, un cierto modelo relacional es requisito previo, claves de alta seguridad, etc. Quinta Forma Normal es, ya que estamos salteando la Cuarta:

    • Tercera forma normal
      • que en términos simples es definitivo, cada columna que no son clave en cada mesa tiene una relación 1 :: 1 a la clave primaria de la tabla,
      • y no con otras columnas que no son clave
    • cero duplicación de datos (el resultado, si es Normalización dilige progresado ntly; no alcanzado solo por inteligencia o experiencia, o trabajando hacia él como un objetivo sin el proceso formal)
    • no Anomalías de actualización (cuando actualiza una columna en alguna parte, no tiene que actualizar la misma columna ubicada en otro lugar; existe en un solo lugar)
      .
  4. Sexta Forma Normal es, por supuesto quinta forma normal, y además:

    • Eliminación de datos que faltan (columnas). Esta es la única solución verdadera al Problema nulo (también llamado Manejo de valores perdidos), y el resultado es una base de datos sin nulos. (Se puede hacer a 5NF con estándares y sustitutos nulos, pero eso no es óptimo.) La forma en que interpreta y muestra los valores perdidos es otra historia.
      .
  5. EAV vs sexta forma normal
    Todas las bases de datos que he escrito, excepto uno, son puros 5NF. He trabajado con (administrado, reparado, mejorado) un par de bases de datos EAV, y he implementado una verdadera base de datos 6NF. EAV es una implementación flexible de 6NF, a menudo realizada por personas que no tienen una buena comprensión de la normalización y las NF, pero que pueden ver el valor y la necesidad de contar con la flexibilidad de EAV. Eres un ejemplo perfecto. La diferencia es esta: porque es flexible, y como los implementadores no tienen una referencia (6NF) para ser fieles, solo implementan lo que necesitan y lo escriben todo en código; eso termina siendo un modelo inconsistente.
    .
    Considerando que, una implementación pura de 6NF tiene un punto de referencia puramente académico, y por lo tanto, generalmente es más estricto y consistente. Normalmente, esto se manifiesta en dos elementos visibles:
    • 6NF tiene un catálogo que contiene metadatos, y todo está definido en los metadatos, no código. EAV no tiene uno, todo está en el código (los implementadores realizan un seguimiento de los objetos y atributos). Obviamente, un catálogo facilita la adición de columnas, navegación y permite que se formen utilidades.
    • 6NF cuando se entiende, proporciona la verdadera solución al problema Null. Los implementadores de EAV, dado que están ausentes del contexto de 6NF, manejan datos faltantes en el código, inconsistentemente, o peor, permiten Nulos en la base de datos. Los implementadores de 6NF no permiten valores nulos y manejan los datos faltantes de manera consistente y elegante, sin requerir construcciones de código (para el manejo de nulos; aún así, debe codificar los datos faltantes, por supuesto).
      .
      Por ejemplo. Para bases de datos 6NF con un catálogo, tengo un conjunto de procs que [re] generarán el SQL requerido para realizar todos los SELECT, y proporciono Vistas en 5NF para todos los usuarios, por lo que no necesitan saber o entender la estructura 6NF subyacente . Ellos son expulsados ​​del catálogo. Por lo tanto, los cambios son fáciles y automatizados. Los tipos de EAV lo hacen manualmente, debido a la ausencia del catálogo.

Ahora, podemos empezar la discusión

"Por supuesto que puede ser más abstracto si de valor están predefinidos (Ejemplo: especialidades podrían tener su propia lista)"

Sure. Pero no te pongas demasiado "abstracto". Mantenga la coherencia e implemente dichas listas de la misma manera EAV (o 6NF) que otras listas.

"Si tomo el enfoque abstracto que puede ser muy flexible, pero las consultas se ser más complejo con una gran cantidad de combinaciones. Pero no sé si esto afecta al rendimiento , la ejecución de estos 'más complejas' consultas '.

  1. combinaciones estén peatonal en bases de datos relacionales. El problema no es la base de datos, el problema es que SQL es engorroso cuando se manejan combinaciones, especialmente claves compuestas.
  2. EAV y las bases de datos tienen más 6NF une, que al igual que los peatones, ni más ni menos. Si tiene que codificar cada SELECCIÓN manualmente, claro, el engorroso se vuelve realmente engorroso.
  3. Todo el problema puede ser eliminado por (a) va con 6NF sobre EAV y (b) la implementación de un catálogo, desde donde se puede (c) generar todo el SQL básico. Elimina toda una clase de errores también.
  4. Es un mito común que une de alguna manera tiene un costo. Totalmente falso La unión se implementa en tiempo de compilación, no hay nada de sustancia para 'costar' ciclos de CPU. El problema es el tamaño de las tablas que se unen, no el costo de la combinación entre esas mismas tablas.Unir dos tablas con millones de filas cada una, en una relación PK⇢FK correcta, cada una de las cuales tiene los índices apropiados (Único en el lado padre [FK]; Único en el lado Niño) es instantáneo; ; donde el índice secundario no es único, pero al menos la columna principal es válida, es más lenta; donde no existe un índice útil, por supuesto que es muy lento. Nada de eso tiene que ver con el costo de la unión. Donde se devuelven muchas filas, el cuello de botella será la red y el diseño del disco; no el procesamiento de unión
  5. Por lo tanto, puede ser tan "complejo" como desee, no hay ningún costo, SQL puede manejarlo.

estaría interesado en saber cuáles son el arriba y desventajas de ambos métodos. Puedo imaginarme por mi cuenta, pero yo no tengo la experiencia para confirmar esto.

  1. 5NF (o 3NF para aquellos que no han hecho la progresión) es la más fácil y mejor, en términos de implementación, facilidad de uso (los desarrolladores como para los usuarios), mantenimiento. El inconveniente es que, cada vez que agrega una columna, debe cambiar la estructura de la base de datos (tabla DDL). Eso está bien, en algunos casos, pero no en la mayoría de los casos, debido al control de cambios implementado, es bastante oneroso. En segundo lugar, debe cambiar el código existente (el código que maneja la nueva columna no cuenta, porque es un imperativo): donde se implementan buenos estándares, eso se minimiza; donde están ausentes, el alcance es impredecible.

  2. EAV (que es lo que ha publicado), permite añadir columnas sin cambios de DDL. Esa es la única razón por la que las personas lo eligen. (El código que maneja la nueva columna no cuenta, porque es un imperativo). Si se implementa bien, no afectará el código existente; si no, lo hará. Pero necesitas desarrolladores con capacidad EAV. Cuando EAV se implementa mal, es abominable, un desastre peor que 5NF mal hecho, pero no es peor que Unnormalised, que es lo que la mayoría de las bases de datos existen (tergiversadas como "Denormalizadas para el rendimiento"). por supuesto, es aún más importante (que en 5NF/3NF) mantener un fuerte contexto de transacción, porque las columnas están mucho más distribuidas. Del mismo modo, es esencial conservar la Integridad Referencial Declarativa: los problemas que he visto se debieron en gran parte a que los desarrolladores eliminaron DRI porque se volvió "demasiado difícil de mantener", el resultado fue, como se puede imaginar, una madre de datos montón con filas y columnas duplicadas de 3NF/5NF en todo el lugar. Y manejo incoherente de nulos.

  3. No hay diferencia en el rendimiento, suponiendo que el servidor se haya configurado razonablemente para el fin previsto. (De acuerdo, hay optimizaciones específicas que solo son posibles en 6NF, que no son posibles en otras NF, pero creo que están fuera del alcance de este hilo.) Y nuevamente, EAV hecho mal puede causar cuellos de botella innecesarios, no más que Desnormalizado.

  4. Por supuesto, si vas con EAV, estoy recomendando más formalidad; comprar el total de quid; ir con 6NF; implementar un catálogo; utilidades para producir SQL; Puntos de vista; manejar los datos faltantes consistentemente; eliminar nulos por completo. Esto reduce su vulnerabilidad a la calidad de sus desarrolladores; Pueden olvidarse de las emisiones esotéricas de EAV/6NF, usar Vistas y concentrarse en la lógica de la aplicación.

Pardon the long long.

+4

Wow, gracias por la respuesta masiva, muy interesante. Por supuesto, tendré que volver a leerlo un par de veces, pero me gustaría preguntar cuál es el recurso más confiable para aprender a dominar el 6NF. Los resultados de Wikipedia y Google no son tan útiles. ¿Dónde/Cómo aprendiste esto? – Moak

+8

Gracias por las amables palabras. No hay tal fuente. Hay buenos libros de texto. La información disponible en la red (para cualquier cosa, no solo este tema restringido) es basura Wiki es un estudio en mediocridad. Usted obtiene lo que acaricia. Un título de TI formal de un buen Uni es el mejor lugar para comenzar. Como bien sabes, el dominio proviene de trabajar con un maestro. AFAIK solo otro proveedor proporciona este nivel de dominio sobre el tema: lo venden como un producto; Lo vendo como un servicio, porque creo que la gente realmente tiene que entenderlo, poseerlo, no tenerlo encerrado en un producto. – PerformanceDBA

+2

Dónde/Cómo. Bueno, hice todo lo anterior, y estoy muy agradecido por los excelentes maestros que tuve. Mejorando alrededor de cuatro bases de datos por año, para grandes bancos, es mi pasión/profesión. Si digo más aquí, sería inmodesto. Si está interesado en más detalles, persígueme: perfil⇢sitio web⇢email. Sería libre de responder tu pregunta. Aclamaciones. – PerformanceDBA

2

El enfoque "abstracto" es mejor conocido como "Normalización", se parece a la 3ra Forma Normal (3NF).

El otro se llama "Denormalized", y puede ser una opción de rendimiento válida ... cuando ha encontrado problemas de velocidad utilizando el enfoque Normalizado, no antes.

+0

¿Quiere decir que uno debe construir el enfoque normalizado y si el rendimiento realmente es un problema, entonces, actualice el hardware o cambie todo el código y cree nuevas tablas? Lo siento, no estoy completamente seguro de lo que me estás diciendo ... – Moak

+0

@Moak: Sí. Hacer un enfoque desnormalizado sin la necesidad es una optimización prematura. –

+0

Como no conozco estas formas normales, ¿podrías sugerir que tal vez debería buscar en la primera, segunda, cuarta, tercera forma u otra forma normal? – Moak

1

¿Cómo se muestran los listados en el código? Supongo que Listing como un supertipo, con Shop, Restuarant, etc. como subtipos?

Suponiendo que sí, este es un caso de cómo asignar subtipos a una base de datos relacional. En general, existen tres opciones:

  • Opción 1: una sola mesa por cada subtipo, con atributos comunes repetidos en cada tabla (nombre, identificación, etc.).
  • Opción 2: tabla única para todos los objetos (el enfoque de una sola mesa)
  • Opción 3: tabla para el supertipo y uno para cada subtipo

No hay una solución universalmente correcta. Mi preferencia generalmente es comenzar con la opción 3; proporciona una estructura intuitiva para trabajar, está bastante bien normalizada y puede ampliarse fácilmente. Significa una unión única para recuperar cada instancia, pero RDBMS está bien optimizado para hacer combinaciones, por lo que realmente no causa problemas de rendimiento en la práctica.

La opción 2 puede ser más eficiente para consultas (sin uniones) pero causa problemas si otras tablas necesitan hacer referencia a todas las instancias de supertipo (proliferación de claves externas).

La opción 1 parece a primera vista la más eficiente, aunque tiene dos advertencias: (1) No es resistente a cambios. Si agrega un nuevo subtipo (y, por lo tanto, atributos diferentes), deberá cambiar la estructura de la tabla y migrarla. (2) Puede ser menos eficiente de lo que parece. Debido a que la población de la tabla es escasa, algunos DB no la almacenan de manera particularmente eficiente. Como consecuencia, puede ser menos eficaz que la opción 1, ya que el motor de consultas puede hacer combinaciones más rápido de lo que puede buscar espacios de tablas escasos e inflados.

Que elegir realmente se reduce a conocer los detalles de su problema.Sugeriría leer un poco sobre las opciones: this article es un buen lugar para comenzar.

hth

8

En su pregunta, ha presentado al menos dos problemas importantes al mismo tiempo. Esos dos problemas son E-A-V y gen-spec.

Primero, hablemos de E-A-V. Su última tabla (object_id, field_id, value) es esencialmente una E-A-V.Hay un lado positivo para E-A-V y una desventaja para E-A-V. Lo bueno es que la estructura es tan genérica que puede acomodar casi cualquier cuerpo de datos que describan casi cualquier tema. Eso significa que puede proceder al diseño e implementación sin análisis de datos y sin comprender el tema, y ​​no preocuparse por suposiciones erróneas. El inconveniente es que en el momento de la recuperación, debe hacer el análisis de datos que omitió antes de construir la base de datos, para poder encontrar consultas que signifiquen algo. Esto es mucho más serio que solo la eficiencia de recuperación. Pero también vas a tener terribles problemas con la eficiencia de recuperación. Solo hay dos maneras de aprender sobre este escollo: vivirlo o leer sobre él de aquellos que lo tienen. Recomiendo la lectura.

En segundo lugar, usted tiene un caso gen-spec. Su tabla (object_id, type_id) captura un patrón gen-spec (generalización-especialización), junto con las tablas relacionadas. Si tuviera que generalizar entre hoteles y restaurantes, podría llamarlo algo así como "alojamientos públicos" o "lugares". Pero no estoy seguro de entender tu caso, y puedes conducir por algo aún más general de lo que sugieren esos dos nombres. Después de todo, has incluido "eventos" en tu lista, y un evento no es un tipo de lugar en mi mente.

He referido a otras personas a las lecturas en gen-spec y el modelo relacional en respuestas anteriores.
When two tables are very similar, when should they be combined?

Pero yo dude que le envíe fuera en la misma dirección, porque no es claro para mí que desea llegar a un modelo relacional de los datos antes de la construcción de su base de datos. Un modelo relacional de un cuerpo de datos y un modelo E-A-V de los mismos datos están casi totalmente en desacuerdo entre sí. Me parece que debes tomar esa decisión antes de explorar cómo expresar gen-espec en el modelo relacional de datos.

1

Cuando empiece a requerir una gran cantidad de entidades diferentes (o incluso antes de ...), una solución nosql sería mucho más simple que cualquiera de las opciones. Simplemente almacene cada entidad/registro con los campos exactos que necesita.

{ 
    "id": 1, 
    "type":"Restaurant", 
    "name":"Messy Joe", 
    "address":"1 Main St.", 
    "tags":["asian","fusion","casual"] 
} 
Cuestiones relacionadas