Antipatrones en bases de datos (@WTMZ23)

Laura Alcober

Laura Alcober

En un sector como es el de la verificación de identidad, donde los sistemas de detección se basan en tecnología de Inteligencia Artificial, se trabaja con un volumen de datos muy elevado por lo que es crucial que el acceso a datos sea eficaz, rápido y que permita realizar operaciones de tratamiento y carga complejas con relativa sencillez.

Es habitual trabajar con volúmenes de millones de usuarios en tiempo real, que combinan información almacenada como datos relacionales o como ficheros externos. Desde Alice Biometrics conocemos muy bien esta operativa y la tenemos integrada en nuestro día a día, tanto para dar un servicio de calidad a nuestros clientes como para incorporar esos datos en el flujo de mejora continua de nuestros sistemas de detección de fraude. Es por eso por lo que conocemos la importancia de dar un tratamiento adecuado a los datos desde su origen: en la construcción de los sistemas que almacenarán los datos.

En las bases de datos relacionales es habitual incurrir en antipatrones cuando se construyen las tablas y los esquemas que la conforman. La forma más fácil de evitar que nuestras bases de datos se conviertan en sistemas poco operativos y complejos de manipular es conocer en qué formas se pueden manifestar estos antipatrones para buscar soluciones adecuadas cuando diseñemos esquemas.

¿Que es un antipatrón?

Un antipatrón es una respuesta habitual que se da a un problema recurrente que suele ser tanto ineficaz como contraproducente, pero que se plantea como la forma más sencilla e incluso lógica de resolver dicho problema.

Made to fit

Uno de los antipatrones más habituales es la delegación completa del tipado de datos a las distintas capas de las aplicaciones. En ocasiones es fácil dejar de lado una definición más precisa de los tipos de datos en la capa de la base de datos puesto que en el paradigma de la programación orientada a objetos (OOP) esa definición se hace ya en nuestra capa de aplicación. Esto puede provocar que corner cases, bugs no detectados a tiempo o errores en la lógica de la aplicación impacten de forma muy inmediata y muy negativa sobre la calidad de los datos. Este antipatrón es un problema importante en cuanto a la rapidez con la que los datos se pueden desvirtuar y lo costoso que suele ser el solventarlo en sistemas vivos con un crecimiento rápido y un gran tamaño.

La forma más fácil de resolver esto pasa por establecer desde el principio unos esquemas sólidos la base de datos, usando las siguientes reglas:

1. Utilizar un tipado de datos sólido

Los motores de bases de datos se auto-optimizan en función a los tipos de datos que guardan sus tablas. Cuanto más específicos se es, más rápida será la base de datos y menos almacenamiento ocupará. En un un entorno tecnológico como es el actual donde impera el almacenamiento en distintos proveedorres Cloud, esto siempre permite reducir costes y ajustar mejor los recursos existentes.

2. Definir de forma precisa que campos no van a admitir valores nulos con la constraint NOT NULL

En linea con el punto anterior, esta medida ayuda a optimizar el rendimiento de la base de datos, acotar más la forma que pueden adquirir los datos y definir mejor las relaciones entre entidades. Adicionalmente sirve como última barrera para evitar que datos que son necesarios para el negocio no estén presentes en las tablas de la base de datos.

3. Aprovecha al máximo las capacidades de tu sistema gestor de bases de datos

Los sistemas de bases de datos incorporan funciones y herramientas específicas para el trabajo con datos relacionales, por lo que en la gran mayoría de los casos resultarán ser los sistemas mejor preparados, más eficientes y más rápidos para, por ejemplo, asegurar la transaccionalidad de la escritura de datos.

Key-Attribute-Value

Otro de los antipatrones habituales en los que se incurre a la hora de crear tablas y columnas sucede cuando se traslada de forma paralela el modelado de objetos al modelado entidades de la base de datos y la construcción de tablas. En el campo de la verificación de identidad donde se trabaja con distintos documentos de identidad, es frecuente que dichos documentos no tengan el mismo número de campos o almacenen los mismos tipos de datos. Una de las soluciones que más se suelen repetir es aquella en la que se opta por almacenar los datos de estos documentos en tablas de la siguiente forma, donde en una columna key se almacena el identificador único del documento, en una columna attribute se almacena el nombre del campo del documento, y por último en una columna value con un tipado poco específico (tipos de datos genéricos muy grandes como TEXT donde la información se almacena en forma de texto plano) se almacena el valor del campo referenciado en attribute.

Esquema, key-attribute-value

Si bien puede parecer una solución sencilla a un problema complejo, porque permite almacenar cualquier tipo de dato para un campo de un documento y permite que los campos de los documentos sean opcionales y solo estén presentes para los documentos en los que sean vinculantes, esta práctica conlleva varios problemas. En primer lugar se pierde toda integridad referencial en la entidad, que es la propiedad de las bases de datos que permiten establecer relaciones con otras entidades y que garantizan que los registros de las tablas relacionadas son válidos y que no se eliminan o modifican por error. Con esta solución no es posible establecer relaciones aseguradas y protegidas entre los documentos almacenados y otros datos que tengamos almacenados, como pueden ser usuarios o incluso documentos de otros tipos. Paralelamente, y como hemos indicado anteriormente, un tipado poco específico de nuestra base de datos puede conllevar problemas de rendimiento, y en este caso concreto se perjudica la edición de los datos almacenados. A este problema existen distintas soluciones, y la primera pasa por combinar nuestra base de datos SQL con un sistema NoSQL que proporciones la flexibilidad que se necesita en estos casos. Si se quiere almacenar este tipo de datos en una base de datos relacional para sacar partido a las funcionalidades que estas nos ofrecen siempre se puede optar por utilizar una estrategia de almacenaje de datos semiestructurados, donde los campos de los documentos que queremos almacenar utilizan columnas con tipado concreto y ajustadas al tamaño de lo que se almacenará en ellas, y en las que se guardarán los campos opcionales o presentes solo en algunos documentos en una columna de tipo de dato semiestructurado como puede ser XML o JSON, que se encuentran en todos los sistemas gestores de bases de datos modernos. Esta solución aporta la flexibilidad del uso de una base de datos NoSQL con las ventajas de mantener nuestros datos interrelacionados.

Esquema, almacenaje de datos semiestructurados

Otra solución posible, si se quieren mantener los datos almacenados en una base de datos relacional, pasa por adoptar un patrón de diseño llamado Class Inheritance a la hora de construir las tablas, en el que se aplican los conceptos de la herencia de objetos sobre el modelado de las entidades. Con este patrón lo que se consigue es una tabla maestra donde se almacenan los datos comunes a todos los documentos y tantas tablas relacionadas como tipos distintos de documentos se tengan. De esta manera es fácil controlar los subtipos de documento existentes mientras se mantiene un tipado más estricto sobre las columnas que almacenan los campos de los documentos.

Esquema, Class Inheritance

Conclusión

En definitiva, existen varios antipatrones de creación de tablas y columnas que pueden provocar que los sistemas de verificación de identidad no saquen todo el partido posible de los sistemas gestores de bases de datos que utilizan. Conocerlos e identificarlos antes de que ocurran es la mejor estrategia posible para que los datos almacenados sean fácilmente accesibles, completos y aprovechables.

Si te ha gustado, comparte en