ActiveRecord::Enum persistido en un campo string. ¿Es una mala idea?

Andrés

30 June 2024

2 mins

 ActiveRecord::Enum persistido en un campo string. ¿Es una mala idea?

Hubo un momento en mis aplicaciones en el que dejé de persistir los campos que iba a definir como enum en campos int y comencé a hacerlo en strings. Tomé esta decisión porque, en varias ocasiones, me pidieron un volcado de la base de datos para su análisis, y cada vez que se encontraban con un campo status (o cualquier otro usando enum) con valores como 0, 1 o 2 me terminaban preguntando sobre su significado. Por lo que, en vez de usar valores numéricos que carecen de sentido y contexto, los cambié directamente por un string que en sí mismo tiene sentido y da contexto.

Pero hace unos días volví a revisar la documentación y encontré una frase que me hizo cuestionarme esto:

Finally it’s also possible to use a string column to persist the enumerated value. Note that this will likely lead to slower database queries

¡Usarlo terminaría en consultas más lentas a la base de datos!

Así que, como buen programador, preocupado de la eficiencia y el rendimiento de mis aplicaciones 🤓, me cuestioné lo que estaba haciendo y, antes de realizar algún cambio, quise comprobar esto. Creé una aplicación simple en Rails conectada a MySQL con dos modelos, uno con un enum persistido en int y otro persistido como varchar con 100,000 registros cada uno. Cerré todas las aplicaciones que podían molestar y ejecuté un benchmark:

                                       user     system      total        real
String Enum Count:                 0.477732   0.052428   0.530160 ( 21.794783)
Integer Enum Count:                0.374897   0.030260   0.405157 ( 21.639400)
String Enum Paginated Index:       0.351621   0.017249   0.368870 (  0.639043)
Integer Enum Paginated Index:      0.317277   0.022936   0.340213 (  0.524883)
String Enum Single Record Fetch:   0.294010   0.031218   0.325228 (  0.489015)
Integer Enum Single Record Fetch:  0.297743   0.015502   0.313245 (  0.497845)

Todos los resultados fueron muy parecidos, las variaciones de tiempo en las 1,000 ejecuciones de consultas simples fueron pequeñas. Si entiendo bien, podríamos tomar el caso de las consultas count. Tuvieron una diferencia de 0.155383s, o sea, 0.1ms de ventaja para int por consulta aproximadamente. Pero para un select con limit(1) ganó el string. Entonces me pregunto, ¿realmente un enum persistido como string terminará en consultas más lentas?

via GIPHY

Bueno, sea más lento o no, creo que en el común de las aplicaciones terminará con diferencias de milisegundos que no serán tan importantes. Por lo que mi razón inicial de comenzar a usar enums persistidos como strings se mantiene como lo más importante. Y no soy el único que tiene una razón para hacerlo, estas dos preguntas en Stack Overflow también buscaban algo similar hace varios años ya:

¿Qué opinas tú? ¿Sabías que un enum puede persistirse como string?

¡Hola a todos! 👋 ¿Disfrutaron leyendo el artículo? ¡Me encantaría conocer sus opiniones! 💬 No duden en dejar un comentario abajo, ya sea para compartir sus comentarios, preguntas o simplemente saludar. ¡No es necesario registrarse, solo compartan algo valioso! 😊
Hey there! 👋 Enjoyed reading the post? I'd love to hear your thoughts! 💬 Feel free to drop a comment below—whether it's feedback, questions, or just saying hi. No need to sign up, just share something valuable! 😊