inmensia |
Modelado de Jerarquías Todo-Parte con Bases de Datos (Agregación)
Juan Mellado, 7 Marzo, 2007 - 19:02
Continuando con la disertación de ayer acerca del modelado de una jerarquía, hoy voy a hablar de la implementación de la relación de agregación. En el sistema de archivos que ponía ayer como ejemplo, la jerarquía en forma de árbol es bastante sencilla de implementar, ya que todos los elementos tienen un único padre y no se permiten ciclos. Para modelar tal tipo de relación basta con que cada elemento guarde una referencia a su padre. La cuestión a considerar es si resulta más conveniente añadir un nueva columna a las tablas de entidades o crear tablas aparte para guardar esas relaciones. Si se decidiera modelar la herencia con dos tablas, entonces cada una de ellas debería tener una columna que hiciera referencia a la tabla de directorios para indicar cual es su padre; la tabla de ficheros haría referencia a la tabla de directorios, y la tabla de ficheros haría una auto-referencia a sí misma. Por el contrario, si se decidiera modelar la herencia con una sola tabla, entonces sólo existiría una auto-referencia a la propia tabla. En ambos casos la única excepción sería el nodo raíz de la jerarquía, que no tiene padre, y que por lo tanto obligaría a dejar vacía la columna y permitir que fuera NULL. Las soluciones del párrafo anterior presentan una serie de inconvenientes. La primera, y que debería llamar enseguida nuestra atención, es el hecho de tener que dejar que la columna pueda tomar valor NULL. Hay algunos diseñadores que opinan que por lo general no es recomendable diseñar tablas con columnas que permitan valores nulos. Sobre todo si, como en este caso, lo que se quiere indicar con el valor nulo es que no existe una determinada relación entre entidades. La forma más correcta de modelar relaciones es a través de tablas intermedias que reflejen tal relación. Si no existe una determinada relación, entonces simplemente no existirá el registro correspondiente en la tabla de relación. Otro problema que se deriva de las soluciones anteriores, si se modela la herencia con dos tablas, es que la jerarquía se distribuye en dos tablas en vez de una. Si con el tiempo aparecen más elementos, para los que se crearían nuevas tablas, entonces la jerarquía se iría expandiendo también por esas nuevas tablas. Hacer consultas o comprobar dependencias entre elementos sería cada vez más complicado. Pero independientemente de que se modele la herencia con una o más tablas, el principal problema de añadir un campo en la tabla para implementar la agregación es que estamos incurriendo en el defecto de mezclar los datos con la forma en que se organizan. Si en futuro cambiara la organización, ¡y siempre cambia!, entonces el modelo dejaría de ser válido. Las entidades se deberían separar, en la medida de lo posible, de cómo se organizan. La forma en la que se organiza la información depende de muy diversos factores, la mayoría de ellos muy subjetivos. Varios departamentos dentro una misma empresa suelen tener visiones muy distintas de una misma información. La manera en la que se presenta la información no debe mandar sobre la forma en la que se almacena. Después de todo lo anterior, debería haber quedado claro que para el ejemplo del sistema de archivos personalmente me inclino más por utilizar una única tabla para las entidades, y otra para las relaciones. ![]() Uno de los principales desafíos que sin duda plantea este modelo es el recorrido de la tabla de relaciones. SQL no fue diseñado originalmente para realizar consultas sobre jerarquías recursivas; no permite que las filas recuperadas durante una consulta hagan referencia a otras filas concretas de esa misma consulta. No se pueden hacer recuperaciones del tipo "dame el hijo de X, y el hijo del hijo de X, y el hijo del hijo del hijo de X, ....". La solución a este inconveniente puede resolverse de dos formas. La primera es recuperando un solo nivel del árbol cada vez, y la segunda utilizando las extensiones que ofrecen algunos gestores de base de datos. Oracle por ejemplo permite realizar consultas sobre estructuras recursivas mediante el uso de cláusulas START WITH y CONNECT BY. Por último, me gustaría comentar que a pesar de la simpleza del modelo, aún quedarían bastantes cosas por definir. La primera sería la correcta elección de tipos para las columnas, aunque a este respecto lo normal es que el proyecto (o la compañía desarrolladora) tenga criterios preestablecidos para dar uniformidad a todos los desarrollos. La segunda sería decidir la clave primaria en la tabla de relaciones; si no se permite que una entidad tenga más de un padre entonces bastaría con definir la clave primaria sobre el ID de la entidad hija, aunque es bastante probable que se tenga que definir un índice sobre el ID de padre para agilizar las búsquedas. La tercera sería tener en cuenta futuras modificaciones o ampliaciones. Un cambio bastante probable sería la necesidad de organizar la información de diversas formas, en árboles con una fisonomía distinta. Para ello bastaría con añadir una nueva columna a la tabla de relaciones que permitiese distinguir un árbol de otro dentro de la misma tabla. ¿No encontró lo que buscaba?Utilice el buscador para encontrar más páginas en esta web o en toda Internet. |