¿Es esta una forma ridícula de estructurar un esquema de base de datos, o me falta algo por completo?

61

He trabajado bastante con bases de datos relacionales y creo que entiendo bastante bien los conceptos básicos del buen diseño de esquemas. Recientemente tuve la tarea de asumir un proyecto en el que el DB fue diseñado por un consultor altamente remunerado. Por favor, avíseme si mi intestino está en contacto - "¡¿WTF ??!?" - está garantizado, o este tipo es tan genio que está operando fuera de mi reino?

DB en cuestión es una aplicación interna utilizada para ingresar solicitudes de los empleados. Con solo mirar una pequeña sección, tiene información sobre los usuarios e información sobre la solicitud que se realiza. Yo diseñaría esto así:

Tabla de usuario:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

Tabla de solicitud

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

Simple, verdad?

El consultor lo diseñó así (con datos de muestra):

Tabla de usuarios

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

DepartamentosTable

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

La base de datos completa está construida de esta manera, con cada pieza de datos encapsulada en su propia tabla, con ID numéricos que unen todo. Al parecer, el consultor había leído sobre OLAP y quería la "velocidad de las búsquedas de enteros"

También tiene una gran cantidad de procedimientos almacenados para hacer referencia cruzada a todas estas tablas.

¿Es este diseño válido para una base de datos SQL pequeña a mediana?

Gracias por comentarios / respuestas ...

Jim
fuente
12
Oh, muchacho, si esto te hace decir WTF, entonces probablemente no hayas visto tablas con más de 200 columnas y procedimientos almacenados de más de 1000 líneas de largo.
Trabajo
42
+1 por no eliminar después de sentirse avergonzado. Gracias por dejar esto para que otros puedan aprender.
Wayne Koorts
2
@Job - en realidad, no lo he hecho - no soy un DBA de oficio (¡bastante obvio ahora! Lol), por lo que mi umbral de SQL WTF es bastante bajo. Sin embargo, el hecho de que me haya perdido por completo el punto del diseño del consultor me hace perder mis propias habilidades. ¿Alguna vez has tenido un día en el que te sientes tonto ?
Jim
99
@ Jim: felicidades, has convertido un día tonto en un día iluminado .
Wayne Koorts
3
¡Maldice a esos consultores altamente pagados!
davidsleeps

Respuestas:

73

Tiene perfecto sentido para mí. Simplemente está muy normalizado, lo que imparte mucha flexibilidad que de otro modo no tendrías. Los datos desnormalizados son un dolor en el trasero.

Blrfl
fuente
su respuesta tiene mucho sentido, y al revisar mi pregunta y el esquema, tal vez sea solo la gran cantidad de tablas que está usando lo que me confundió. Simplifiqué enormemente el ejemplo de mi pregunta, pero veo cómo suena el concepto: simplemente está dividiendo las cosas mucho más de lo que lo haría yo. Suspiro, supongo que es bueno que no sea un DBA. :)
Jim
Aprenda a diseñar según la regla de los diez minutos: "Lo que es cierto ahora probablemente no lo hará en diez minutos". Asegúrese de que sus diseños puedan lidiar con el cambio.
Blrfl
1
Este esquema realmente tiene la ventaja de que cuando se inserta un empleado, su departamento tiene que existir.
Simon Richter
@SimonRichter: No es cierto. El empleado se puede crear sin ningún departamento existente, y también al revés.
Daniel Dinnyes 01 de
@SimonRichter El beneficio de este diseño es, en primer lugar, que el Departamento es una entidad separada y, en segundo lugar, que existe una relación de muchos a muchos entre el Departamento y el Empleado, a diferencia del ejemplo de OP, donde era "muchos- to-one-ish "(no podría decir muchos-a-uno, ya que ninguna entidad del Departamento separada hacía referencia para ser llamada una relación).
Daniel Dinnyes 01 de
48

No creo que un WTF esté garantizado o que el tipo esté haciendo algún tipo de diseño de genio loco: es una normalización de base de datos bastante estándar.

El motivo de la tabla de departamentos es que si no coloca los departamentos en una tabla separada, tendrá que tratar con los usuarios en los departamentos de "Ventas", "ventas", "Vendedores", "Velas" y "Ventas", a menos que haga algo para evitarlo. Y tener la mesa extra es (parte de) la mejor forma en que sé hacer eso.

Si debería haber una tabla de UserDepartment es una decisión más difícil, lo que, por supuesto, significa que ninguna de las decisiones es descabellada. Por un lado, es una molestia cuando todo el diseño y la lógica de su tabla habían asumido un departamento por usuario y luego eso cambia, por otro lado, hacer una unión adicional sin razón por años y años es una posibilidad real y también un dolor.

Personalmente, estoy de acuerdo con usted en que la tabla de UserDepartment probablemente sea exagerada. Incluso si está incluido, es probable que con el tiempo las personas escriban consultas que asumen que solo hay un usuario por departamento, por lo que terminará con lo peor de ambos mundos: una unión adicional sin ningún motivo antes de necesitar la tabla, y el código no funciona de todos modos una vez que se permite más de un departamento por usuario.

EDITAR: un factor clave para determinar si se debe admitir la relación de muchos a muchos es si las reglas de negocio son claras. Si no tiene idea de cómo funcionaría un usuario en varios departamentos, no tiene mucho sentido agregar la tabla, ya que su código no puede manejar correctamente los casos en los que un usuario está en varios departamentos.

Imagina que permitiste muchos departamentos por usuario, por si acaso. Luego implementó una regla comercial para asignar comisiones, según el departamento. Luego se permitieron múltiples departamentos. Afortunadamente, también tuvo la previsión de escribir su código de comisión de una manera que tuviera esto en cuenta. Desafortunadamente, agregó las comisiones de cada departamento para los usuarios de ambos. La gerencia quería que usted se base en el rol de personas para cada venta. Entonces, ¿qué tan bueno era tener la mesa de antemano? ¿Qué pasa con las otras tablas que tenía "por si acaso" que nunca son necesarias?

EDICIÓN MÁS TARDE: Otra razón por la que el consultor podría haber querido agregar todas esas tablas intermedias se aborda en esta pregunta de seguimiento , cuyas respuestas dan algunas razones por las que la refactorización de una base de datos suele ser más difícil que la refactorización del código, lo que tenderá a empujarlo hacia el enfoque de "poner en todas las tablas que pueda necesitar".

psr
fuente
Creo que pusiste en palabras cuál era mi WTF: el tipo está usando TONELADAS de estas tablas intermedias, y me pareció tan estúpido. Ahora que lo he dividido en un ejemplo mucho más pequeño para esta pregunta, me siento bastante estúpido por publicarlo, ya que no parece tan malo.
Jim
55
Como puede ver en muchos de los comentarios, existe un escepticismo saludable sobre "solo habrá una X por Y". El consultor se está cubriendo de quejas de "por qué solo puede haber una X por Y". Algunos de los cuales probablemente aparecerán. Pero él no será responsable de mantener el código que tiene muchas uniones (no está mal, pero es más difícil) y que tiene que ser correcto contra las reglas comerciales que aún no existen (mal). Imagine la pregunta "¿por qué los usuarios obtienen TODO? los permisos de cada departamento, deben obtener el MÁS BAJO de cada permiso "o algo así.
psr
@psr Creo que hay un error tipográfico: ¿no deberían las "consultas que suponen que hay un solo usuario por departamento" ser "consultas que suponen que un usuario está en un solo departamento"?
BiAiB
@BiAiB: tienes razón, eso es lo que quise decir.
psr
14

Si el requisito es tener varios departamentos por usuario, este diseño tiene sentido. La única queja de ello es el UserDepartmentTableque tiene una clave sustituta UserDepartmentIDque no es necesaria (al igual que el UserIdy DepartmentIduna clave principal compuesta).

Si un usuario solo pertenece a un solo departamento, su diseño tiene sentido (aunque una tabla de búsqueda de departamento aún sería algo bueno).

Oded
fuente
18
... Hasta que sea posible más de un departamento por usuario.
Blrfl
1
Exactamente, @Blrfl. Lo que nunca sucederá hoy es el futuro CEO de tener un aneurisma porque no lo hace.
Adam Crossland
2
Parte de decidir lo que es digno de ese tipo de tratamiento es comprender el dominio del problema. En algunas aplicaciones, puede ser importante saber que la empresa conoce al empleado # 3804 como Ann Smith y Ann Jones (después de casarse), lo que haría normalizar el nombre de la tabla de empleados. En el caso de Jim, podría valer la pena ampliar la tabla de interruptores para mantener un historial de modo que si Ann pasa de RRHH a TI, el hecho de que una solicitud anterior vinculada a ella pudiera reflejar que realmente era una solicitud de RR.HH. y no de TI.
Blrfl
8
YAGNI: las bases de datos se pueden refactorizar.
JeffO
2
@Oded, algunos mapeadores de ORM como Entity Framework no funcionan bien con tablas que tienen una clave primaria compuesta.
maple_shaft
5

Algunos requisitos no están claros en su pregunta. La respuesta correcta depende de lo que quiera su cliente: si yo fuera usted, le preguntaría al cliente sobre esto:

0-¿Cuál es la diferencia entre un usuario y un empleado?

1-Suponiendo que un empleado = usuario, ¿qué pasa si un empleado cambia de departamento?

2-¿Puede un grupo de empleados hacer 1 solicitud?

3-¿Podría un empleado pertenecer a más de un departamento? ¿Qué hay del CEO?

4-¿Hay un subconjunto de empleados que pueden hacer solicitudes?

5-¿Qué sucede con la solicitud cuando se elimina un registro de empleado (si alguna vez)?

6-¿Podrías borrar una solicitud? Qué sucede cuando se elimina la solicitud (asegúrese de no eliminar el registro de empleado de RI)

7-¿Puede el empleado hacer la "misma" solicitud más de una vez (definir la "misma")

8-Cómo manejar las solicitudes de los empleados cuando dejan la empresa (¿cancelar sus solicitudes o eliminar las solicitudes?)

Puede haber más preguntas, pero mi punto es que la solución depende de los requisitos exactos y del alcance del proyecto. Una vez que se determina, el esquema se puede derivar directamente. En consecuencia, ambas soluciones presentadas pueden ser correctas.

Ninguna posibilidad
fuente
+1 estas son excelentes preguntas que deben aclararse antes de diseñar este tipo de esquema. Me gusta tu flujo de lógica.
@ Surfer513: Agradezco tu bonito comentario.
NoChance
1

Me gustaría agregar un par de notas en forma de puntos que expliquen explícitamente algunas de las ventajas potenciales de usar una tabla de unión de la manera en que lo hizo su consultor altamente remunerado.

  • Indizado correctamente (por ejemplo, si UserDepartmentTable indexa las dos claves externas), solo hay una pequeña pérdida de rendimiento de una tabla de unión como esta debido a que las claves externas no son únicas. Si se garantiza que las claves foráneas sean únicas, según la pequeña teoría de la base de datos que conozco, buscar UserDepartmentTable.Departmentno es "más difícil" que buscar cualquier otra columna de la Usertabla.
  • La tabla de unión le brinda más flexibilidad para configurar otra información sobre la asociación entre el usuario y el departamento (por ejemplo, marcas de tiempo en la creación).
  • La tabla de unión le permite "versionar" la asociación con bastante facilidad (p. Ej., Cuando un usuario cambia de departamento, UserDepartmentTable.Activeactiva un indicador booleano de índice como falso y crea una nueva asociación que está activa). También es posible tener versiones de asociación de departamento con el modelo de dos tablas (solo Usuario y Departamento), pero es más difícil y necesita agregar al menos una columna más o realizar acrobacias de la base de datos para evitar duplicar las claves principales.
  • Le permite asignar asociaciones uno a muchos o muchos a uno o muchos a muchos con bastante facilidad.

Dicho esto, hay varias razones para NO hacer lo que hizo su consultor altamente remunerado.

  • Todos los beneficios anteriores son anticipatorios de posibles necesidades futuras, complicando demasiado las cosas para el día de hoy. No es compatible con YAGNI. Más tarde es de poca importancia escribir una migración que se mueva de su modelo de dos tablas a un modelo de tabla de unión. Puede hacerlo cuando surja la necesidad del negocio. Hacerlo antes de eso puede ser confuso.
  • Confunde a otros desarrolladores. Si bien, sí, diría que la expectativa para un desarrollador web de su estatura (donde está revisando las decisiones de los consultores) sería comprender y reconocer una mesa de unión, aún es más complicado de lo necesario y teniendo en cuenta la falta de necesidad comercial, Causa confusión.
Steven
fuente
buen análisis, sin embargo, no diría que tengo ninguna estatura como desarrollador en mi trabajo diario, excepto que soy el único aquí que sabe algo sobre db / c # / vb / etc ... así que supongo que soy parte tiempo de desarrollo por defecto. este es un proyecto bastante pequeño, por lo que los consultores por su gran cantidad de mesas y me unieron me dejaron diciendo "wtf" (pero gracias a ustedes, gente excelente, ahora estoy diciendo "oic ...")
Jim
Un tema bastante antiguo, pero aún relevante ... la refactorización puede ser muy difícil, imagine que necesita varios departamentos en el futuro en lugar de uno, pero solo tiene una ID de departamento en Usuarios como FK. Probablemente terminará con referencias duplicadas (Users.DeptID y UsersDepartmentsTable) o basura completa, como listas separadas por comas en Users.DeptID o XML. La solución correcta no podría agregarse fácilmente, como lo sugirieron YAGNI o KISS, pero sería obstruida.
Erik Hart
0

Sin la estructura completa de la información necesaria, no puedo decir si es terrible o no. Pero al menos la pieza mostrada no es de diseños "WTF". Parece que es la 3ª forma normal de estructura de datos (bueno, teóricamente también tenemos 4ª y 5ª también)

Algunas conversaciones pueden tener lugar para UserDepartmentTable entre dos escuelas de claves "naturales" y "artificiales" en la pieza mostrada. Nada más, como puedo ver

La normalización es la regla de un buen desarrollador / diseñador de bases de datos por muchas razones, las normalizaciones * de * se usan a veces en medio de los desarrollos para ganar velocidad principalmente

Tejón perezoso
fuente