Base de datos

La pieza más importante en el análisis de una aplicación es sin duda la base de datos. Podríamos afirmar que un buen diseño de base de datos garantiza rendimiento y mantenibilidad mientras que un mal diseño nos garantiza problemas que se irán agravando con el paso del tiempo.

Demos tratar de diseñar nuestra base de datos con la mayor sencillez posible, de lo contrario cualquier corrección, mejora o evolución se convierte en una tarea compleja y por lo tanto mucho más costosa. A continuación vamos a ver algunas buenas prácticas a la hora de diseñar la estructura de base de datos de nuestra aplicación.

Una base de datos, un responsable

Dada la importancia de la base de datos es fundamental que esté bajo la tutela de un único responsable. Esto no significa que solo una persona pueda hacer cambios, que también puede ser una buena práctica, sino que no debería de realizarse ningún cambio en la base de datos sin que el responsable esté informado y valide dicho cambio. Ya que de no hacerse así corremos el riesgo de que la base de datos contenga campos que ya no se utilizan pero que nadie se atreve a borrar, índices duplicados en tablas muy grandes donde es más difícil controlar todo lo que ya existe, etc. En definitiva, cada base de datos debe tener un responsable único.

Esquemas

Crea esquemas para documentar las tablas

Cuando comenzamos a desarrollar una aplicación lo haremos desarrollando la estructura de base de datos, para realizar esa tarea es recomendable crear un objeto esquema que nos permitirá crear las tablas de forma visual y además dejarlo documentado para en el futuro poder recordar de un vistazo las relaciones entre las diferentes tablas. El objeto esquema hace bueno el dicho "Una imagen vale más que mil palabras".

Conviene crear las tabla directamente desde el esquema ya que además de crear el objeto ya lo dejamos incrustado en el esquema lo que nos facilitará crear las relaciones de forma visual.

Crea múltiples esquemas

A medida que vamos añadiendo tablas a nuestro proyecto conviene crear múltiples esquemas con el doble objetivo de evitar tener un esquema con tantas tablas y relaciones que resulta muy complicado ver la estructura y entenderla, y por otro lado nos permite tener esquemas específicos con la estructura de sub módulos o funcionalidades específicas, consiguiendo que otros desarrolladores entienda la estructura de tablas y sus relaciones rápidamente.

Número de tablas y tamaño de registros

¿El número de tablas influye en el rendimiento?

Salvo que estemos hablando de miles de tablas, en cuyo caso podría afectarnos en el tiempo de reinicio de la instancia en el servidor, a nivel de ejecución hay que tener en cuenta que nos afectan las tablas en uso, no las declaradas en el proyecto.

¿El tamaño de registro de una tabla como influye?

Influye en el tamaño de las transacciones, en el nº de conexiones que un cliente tiene que establecer con el servidor para obtener los datos de una lista de registros y en los tiempos de regeneración de la tabla ante un cambio de estructura.

Por lo tanto debemos intentar reducir el tamaño de registro de una tabla en la medida de lo posible. Unas buenas prácticas podrían ser:

  • Evita crear campos que no se usan.

  • Si se necesitan campos alfabéticos muy largos (>100 caracteres) que se usan en un porcentaje bajo de registros, puede ser más óptimo crearlo de tipo objeto texto, de esta forma en el registro ocupa 8 bytes y en el contenedor las celdas que necesite de 512 bytes.

  • Evita la información repetida, por ejemplo, intenta no duplicar el nombre de los artículos en las líneas de movimientos.

  • Extrema el tamaño de registros en las tablas que vayan a contener millones de registros.

¿Es mejor tener muchas tablas con un único tipo de registro o es mejor tener una única tabla con múltiples tipos de registro?

Si el número de registros no es elevado, es decir no contendrá la tabla millones de registros) será más cómodo crear una única tabla con un campo que identifique el tipo de registro.

El campo de tipo de registro para que esté bien documentado debería apuntar a una tabla estática evitando así tener que documentar los valores del mismo por los diferentes lugares de la aplicación donde se use.

Otro factor a tener en cuenta es el número de índices que se van a crear. Si por ejemplo vamos a crear los típicos índices de código, nombre, palabras y trozos y tenemos 5 tipos de registros vamos a crear 20 índices. Este valor no es un problema, pero si vamos a tener que crear un número alto de índices (>200) tal vez debemos replantearnos el uso de tablas independientes.

Hay que tener en cuenta que aunque esta tabla tenga muchos índices, estarán condicionados de tal forma que en cada índice solo encontraremos los registros de un determinado tipo.

Tipos de tablas

¿Cuándo es conveniente usar una tabla de tipo maestro arbolada?

Cuando tengamos que representar los registros de dicha tabla en un árbol en el que cada nivel representa una relación de herencia entre los registros.

Ejemplo habituales son el plan de cuenta de contabilidad, clasificaciones de familias y subfamilias, etc.

¿Qué tamaño de campo ID debo usar en una tabla arbolada?

El menor posible que te permita contener el mayor código que se necesita grabar. Es decir, debemos evitar poner un campo código en el que dejemos un tamaño mayor "por si acaso".

Hay que tener en cuenta que el tamaño del ID influye en los índices y también en el tamaño de los campos que apuntan a esta tabla como maestra. Por lo tanto afecta al rendimiento, cuanto menor sea el código más rápido se manejará la tabla.

Por este motivo se suelen usar campos alfabéticos “comprimidos” como el Alfa 64 (Ahorro del 25%) y Alfa 40 (Ahorro del 33%) que nos permiten contener más caracteres en el código con una menor ocupación en disco.

¿Cuándo es conveniente usar tablas de tipo histórico?

Cuando se den las 2 siguientes circunstancias:

  1. La tabla no tiene un código único que identifique al registro sino que almacena información que no está codificada, o tiene múltiples maestros relacionados, todos ellos con el mismo peso.

  2. La tabla nunca será maestra de otra tabla plural. Esto se debe tener en cuenta para que en el caso de que exista un plural no nos veamos obligados a incluir múltiples campos punteros para resolver la clave única que se haya creada en esta tabla histórica.

¿Y si creo siempre todas las tablas maestras?

Es cierto, que evitar crear tablas históricas y en su lugar crearlas siempre como maestras nos evita la 2ª circunstancia de la pregunta anterior, y es cierto que en la mayoría de los casos nos servirá aplicar este criterio de todas maestros.

Sin embargo, existen algunas excepciones que debemos tener en cuenta.

Si tengo que apuntar a una tabla con punteros indirectos reales usando campos para resolver el índice de clave que no es el ID, no me sirve de nada que la tabla sea maestra, al contrario me obliga a mantener un campo y un índice innecesarios.

Si creamos la tabla como maestra y apuntamos a ella a través del código (ID) obteniéndolo con una búsqueda por otro de sus índices de clave única compuesto por uno o varios campos que no son el ID, tendré problemas de refactorización de datos en el caso de que cambien los campos que componen el índice de clave, esto me obligaría a tener que programar el control del cambio de valor de dichos campos. Por ese motivo es preferible apuntar los registros de este tipo de tablas con punteros indirectos que reaccionan automáticamente al cambio de valores con los que se resuelve el puntero al índice de clave única.

Por ejemplo, una tabla de estadística cuyo índice de clave única viene dado por los campos empresa, año, mes y cliente, deberíamos apuntar desde la tabla que actualiza sus datos a través de un puntero indirecto resuelto con campos de la tabla. En este caso definir la tabla como histórica puede ser una buena práctica.

¿Cuándo es conveniente usar tablas de extensión?

Esta tipo de tabla debemos verla siempre como una solución a un problema que no tenga otras alternativas y crearla solo cuando no nos quede más remedio.

Los casos más habituales son:

  1. Tengo que añadir campos a una tabla que está en un proyecto (núcleo estándar) que no puedo o quiero modificar porque cuando se vuelva a actualizar estaría obligado a repetir los cambios. En general son personalizaciones para un cliente concreto sobre una tabla estándar para todos mis clientes o los de un sector.

  2. Cuando tengo una tabla con cientos de miles o millones de registros y hay un grupo de campos que se usan en un % bajo de registros (<20%) y que hacen crecer el tamaño del registro de forma significativa, por ejemplo pasamos de un tamaño de registros de 400 bytes a 3.000 bytes.

¿Por qué hay que evitarla en la medida de lo posible? Fundamentalmente para aplicar el principio de sencillez que facilite su desarrollo y posterior mantenibilidad. Pero no debemos sacar la conclusión de que no debemos usarla, simplemente usarla con rigor y en los casos en los que sea estrictamente necesario.

¿Cuándo es conveniente usar tablas submaestras?

Como su nombre indica es conveniente cuando una tabla tiene una dependencia directa de una tabla maestra, de tal forma que podemos asegurar que no tiene sentido que exista un registro en la tabla submaestra sin que exista previamente el registro de la maestra.

Un caso típico de esta tabla son las tablas de líneas de detalle de las tablas de documentos de compra y ventas.

La ventaja de declarar esta tabla es que el índice ID está formado por el código de la maestra y el código numérico de la submaestra que se numera automáticamente. Si el código de la submaestra no es numérico entonces perdemos esta ventaja y no merece la pena hacerla submaestra.

El otro motivo por el que se desaconseja su uso es que si esta tabla va a tener plurales es mejor usarla de tipo maestra ya que de lo contrario nos encontraremos que para apuntar a un registro desde otra tabla plural vamos a necesitar mínimo 2 campos (maestro y código).

Por el mismo motivo tampoco es cómodo crear tablas submaestras de múltiples niveles ya que cada vez el índice ID tiene más partes y al relacionar otras tablas con esta submaestra se necesitan tantos campos como partes componen el índice, en cambio con una tabla maestra sabemos que podemos resolver la relación con un solo campo.

A continuación veamos unos consejos de buenas prácticas de rendimiento relativas a:

Última actualización