Acerca del modo de almacenar imágenes de productos en PrestaShop

26019 lecturas
2013-04-19 (actualizada el 2022-01-17)
Como otros sistemas de tienda online, al principio PrestaShop guardaba los archivos de imagen de productos en un único directorio. A comienzos de la serie 1.4, se pensó acertadamente que es mejor organizarlos en subcarpetas. Pero la forma concreta de hacerlo fue una cagada.
Imagen de Acerca del modo de...

Efectivamente, guardar todos los archivos de imagen de producto de la tienda online en un único directorio, no es lo más conveniente, sobretodo si se trata de un catálogo de productos muy amplio.

Hoy día, gracias a importadores de productos como PrestaImport, no es necesario meterlos a mano y podemos encontrar tiendas con miles de productos a la venta. Pero vamos a tomar como ejemplo un número nada exagerado de productos: 333. Suponiendo que cada producto tiene 3 imágenes, eso son 999 imágenes, y teniendo en cuenta que PrestaShop guarda cada imagen en 5 tamaños distintos (según el theme), más la original, eso son 6 archivos por cada imagen, lo que hace un total de 5.994 archivos de imagen.

Teniendo en cuenta que a partir de 500 archivos en un mismo directorio el rendimiento del disco duro se resiente, es una buena idea tratar de organizar esos 5.994 archivos de imagen en subcarpetas, y así lo planeó el equipo de desarrollo de PrestaShop, en los comienzos de la serie 1.4.

Sin embargo, se pasaron tres pueblos, en lo que a la postre se ha revelado como un ejemplo de cagada en la toma de decisiones dentro de la ingeniería del software.

Se decidió organizar los archivos de imagen de esta forma:

Cada imagen está registrada en la base de datos con un identificador unívoco, que es un número entero. Pues este número se utiliza como guía para determinar en qué subdirectorio guardar los 6 archivos correspondientes a la imagen en cuestión, más un archivo index.php que PrestaShop pone para evitar que se pueda visitar directamente la url correspondiente a ese subdirectorio. Se descompone el identificador en dígitos y para cada dígito se va entrando en un subdirectorio, creándolo si no existe.

Por ejemplo, a la imagen id. 1 le corresponderá el subdirectorio 1/, a la imagen 11, el subdirectorio 1/1/, y a la imagen 111, el subdirectorio 1/1/1/. O a la imagen 352, el subdirectorio 3/5/2/. Como ves, por cada dígito hay un nivel de profundidad en el árbol de directorios.

Hasta ahí bien, pero ¿a nadie se le ocurrió hacer cuentas? ¿no veían que se podía crear un número excesivo de directorios? Tal vez te estás preguntando "bueno, ¿y dónde está el problema?". Te lo voy a contar. Para empezar, intenta bajarte o subir por FTP las imágenes de productos de una tienda PrestaShop. Es desesperante, ya que para cada cambio de directorio, hay que enviar una solicitud al servidor, y, aunque no sea un número excesivo de imágenes (en nuestro ejemplo, 999), resulta muuuy lento. Pero este no es el principal problema.

Vamos primero a hacer cuentas. Tenemos 999 imágenes, cuyos identificadores son correlativos, comenzando por el uno hasta el 999. Dentro de la carpeta img/p/, de imágenes de productos de PrestaShop, tendremos 9 subcarpetas, llamadas del 1 al 9 (no hay carpeta cero porque no existe la imagen con identificador cero). Dentro de cada una de esas 9 carpetas, tendremos 10 carpetas, llamadas del 0 al 9 (hay carpeta cero que se correspondería con el identificador de imagen 10, 20,...), y dentro de cada una de esas 10 carpetas, otras 10 carpetas llamadas del 0 al 9. Estos son los directorios necesarios para almacenar los archivos de esas 999 imágenes: 9 * 10 * 10 = 900 directorios. Y esos directorios contendrán en total 999 * (6 + 1) = 6.993 archivos (999 imágenes por 7 archivos, que son 6 archivos .jpg más el index.php).

Vale, hasta ahí seguimos bien, pero vamos a estirar un poquito la cosa, vamos a poner 3333 productos en vez de 333. Entonces serían 9999 imágenes (3 por producto), lo que resultaría en 9 * 10 * 10 * 10 = 9.000 directorios, y 9999 * 7 = 69.993 archivos. Esto supone un consumo de 9.000 + 69.993 = 78.993 inodes en el disco duro. Pero, ¿qué es un inode?

Los inodes vienen a ser el total de directorios y archivos existentes en la unidad de disco. Y existe un límite, primero determinado por la propia unidad, pero en los alojamientos web compartidos y en los servidores virtuales suele fijarse un límite, arbitrario, ya que se entiende que un consumo excesivo de inodes afecta al rendimiento del disco. Puedes encontrar límites de 100.000, 215.000, 430.000,... Si tu alojamiento es un servidor dedicado, estaremos hablando de un límite de varios millones de inodes, pero el caso es que la mayoría de quienes montan una tienda online PrestaShop no cuentan con esa capacidad y se enfrentan a esos límites más bajos.

Hay tiendas que cuentan con miles de productos, por ejemplo con PrestaImport se están importando catálogos de una media de 5.000 productos, y estamos viendo que el consumo de inodes crece de forma exponencial con el número de imágenes, con lo cual es muy fácil alcanzar el límite de inodes impuesto por el proveedor de alojamiento. No olvides además que las imágenes de los productos no es lo único que hay en el disco. He visto un límite de un millón y medio de inodes ser desbordado por una tienda PrestaShop con 40.000 productos y 110.000 imágenes de producto.

El efecto de agotar los inodes disponibles es que no se podrán crear nuevos directorios ni archivos en el disco, al intentarlo se obtendrá un error de disco lleno, aunque en realidad tengamos varias gigas de espacio de sobra. Y claro, en esa situación queda la web (y nuestro hosting) prácticamente inutilizable.

A veces, los límites impuestos por los proveedores de hosting son demasiado bajos, sobretodo comparados con otras características del alojamiento, como el espacio en disco o la transferencia, pero eso no quita que el equipo de desarrollo de PrestaShop pudo haber ideado un método mucho menos "generoso" con el consumo de inodes. Por ejemplo, simplemente siguiendo la misma idea, pero utilizando el identificador de producto en vez de el de imagen para determinar el directorio donde guardar los archivos, ya estaría reduciendo el consumo considerablemente. A cada producto le correspondería un directorio, donde se meterían todos los archivos de sus imágenes, en vez de un directorio por cada imagen. Estaríamos ahorrando en directorios, y en archivos (por los index.php que no se crearían).

Por supuesto, los archivos de imagen tienen que existir, ahí no hay ahorro, por lo que si vas a montar una tienda con PrestaShop y a poner a la venta un gran número de productos, elige bien tu hosting. Además, este es sólo un ejemplo de los problemas de consumo y rendimiento del sistema de tienda online PrestaShop, que, a pesar de todo ello, es estupendo y yo lo recomiendo, pero siempre conociendo todo lo que hay que tener en cuenta.