Decidiendo entre campos tipo BOOLEAN y ENUM para almacenar flags en MySQL

Decidiendo entre campos tipo BOOLEAN y ENUM para almacenar flags en MySQL

Cuando se esta trabajando con bases de datos MySQL, puede que necesites manejar flags o estados para tus elementos y obviamente lo primero que se viene al a mente es hacerlo a través de campos tipo BOOLEAN, y aunque no es una mala decisión también puedes evaluar el uso de un campo tipo ENUM y eso es lo que explicaré en este artículo.

Un campo ENUM es un tipo de dato que permite que se seleccione un valor de una lista predefinida de valores, piénsalo como drop-down o un select-box, donde las opciones ya están definidas y solamente se puede seleccionar una de ellas, esto puede ser sumamente útil para almacenar flags, como por ejemplo un campo llamado "rol" en una tabla de usuarios, donde puedes tener administradores, revisores, redactores, lectores o cualquier otro tipo de usuario que imagines, específicamente, aquí hay algo importante que notar y es que claramente todos los posibles valores podrían ser flags de tipo BOOLEAN, pero al utilizar un campo tipo ENUM podrías tener algunas ventajas.

CREATE TABLE usuarios (
    ...
    rol ENUM ('administrador', 'revisor', 'redactor', 'lector') DEFAULT 'lector',
    ...
);

Una de las ventajas más obvias de utilizar un campo de tipo ENUM para almacenar flags, es que se simplifica el esquema de base de datos, entonces imagina que en lugar de tener varios campos BOOLEAN, solamente tienes uno solo, el cual puede contener una sola opción, algo muy importante a tener en cuenta cuando se utiliza un campo tipo ENUM, es que será un campo que agrupe diferentes opciones que todas están dentro de un mismo contexto, para ejemplificar el caso de como se definiría la tabla usuarios utilizando campos booleanos, pues se vería de la siguiente manera:

CREATE TABLE usuarios (
    ...
    es_administrador BOOLEAN DEFAULT false,
    es_revisor BOOLEAN DEFAULT false,
    es_redactor BOOLEAN DEFAULT false,
    es_lector BOOLEAN DEFAULT false,
    ...
);

Otra ventaja del uso de campos de tipo ENUM es que las tablas se vuelven más compactas en tamaño y peso, ya que en lugar de tener 4 campos como en el ejemplo, el esquema se ha reducido a un solo campo, aparte de que el espacio de la tabla también es más pequeño porque no se estarían utilizando 4 bytes (1 por cada BOOLEAN), sino que es solamente sería 1 byte por único campo y es que hay algo interesante aquí, y es que aunque nosotros vemos que un campo tipo ENUM almacena cadenas de caracteres como posibles opciones, internamente el motor de DB mapea los valores hacia enteros, quedando como 1 - administrador, 2 - revisor, 3 - redactor, 4 - lector, la DB es suficientemente inteligente para saber que tipo de longitud utilizar para los campos tipo ENUM y por omisión, estos empiezan con tinyint y conforme las opciones se van extendiendo, la longitud cambia a small int, medium int, etc. Y en términos de performance, localizar valores enteros es mucho más rápido y eficiente que buscar cadenas, pero ya quedó claro que los ENUM no usan cadenas.

Hasta aquí todo bien, pero no todo es maravilloso con los campos tipo ENUM, también se tienen algunas desventajas, como por ejemplo, al agregar un nuevo valor a la lista, se necesitaria hacer un ALTER TABLE lo que provocaría (dependiendo del motor) que la tabla de bloquee mientras se re-indexan los valores después del cambio, esto último podría ser una tarea bastante cara en términos d eprocesamiento, si estamos hablando de una tabla con millones de registros que deben actualizarse.

Otro potencial problema es que los campos tipo ENUM no pueden contener valores NULL, entonces si por alguna razón decides introducir el valor NULL como parte de las opciones, a sabiendas de que no se puede, tendrías que agregar el valor NULL como otra opción y no sería entonces un NULL real, sino una cadena con el texto NULL y por ende, la re-indexación ocurrirá de todas formas (muy fea solución).

En general, cualquiera que sea el caso en que decidas utilizar ENUM o BOOLEAN, siempre es importante evaluar los requerimientos, los tipos de posibles valores a almacenar y hasta pensar en la extensibilidad de la tabla, pero definitivamente si se trata de almacenar flags, que de nuevo, todos están dentro de un mismo contexto, es mejor utilizar ENUM a BOOLEAN.

Y para finalizar, una recomendación es que ENUM es una buena opción para almacenar un pequeño número de valores discretos excluyentes, pero definitivamente si las opciones son muy pequeñas, tanto así como para almacenar TRUE o FALSE, mejor continúa utilizando un campo de tipo BOOLEAN. También me refiero a un pequeño número de valores, porque al tener muchos valores, esto puede traerte problemas en términos estructurales, posible puede ser, pero no recomendable, entonces para el caso de muchos valores, lo mejor sería tener un campo de tipo INT indexado, que haga referencia a algún catálogo donde las operaciones de adición, edición o eliminación de opciones no afecta el desempeño de la tabla que contiene el índice.

Happy coding! :D


Photo by Nathan Dumlao on Unsplash

Jack Fiallos

Jack Fiallos

Te gustó este artículo?