Si venís del mundo de las bases de datos relacionales, ya no digamos si usáis bases de datos No-SQL, os habréis fijado en dos cosas que ocurren cuando desarrollamos con WordPress. La primera es que las bases de datos «engordan» mucho en proporción a cómo lo harían. Lo segundo, relacionado con lo primero, lo lento que es haciendo consultas a la base de datos en proporción a otras soluciones.
De hecho seguramente hayáis oído en alguna charla de rendimiento, que el gran cuello de botella de WordPress es la base de datos. Y la solución que todos plantean es cachear lo cacheable. En WordPress hay que ir siempre bien cacheado para minimizar las llamadas a base de datos, siempre que se pueda claro.
Este problema que os voy a contar es conocido internamente y bueno, aunque es parte de su naturaleza, digamos que algunas partes que son realmente «agresivas» con la base de datos, como WooCommerce, están cambiando su filosofía para que parte de sus datos no se guarden en la famosa tabla posts.
La tabla posts
En WordPress, todos el contenido se guarda principalmente en la tabla post. Ya sea una página, un pedido (por eso que los pedidos en WooCommerce no llevan un orden correlativo), un producto, una variación o una entrada.Todos los tipos de datos, personalizados o no van ahí. Esa tabla tiene una estructura algo «escasa» para lo que podría llegar a guardar. Pero sí, aunque sea escasa en relación a otras tablas similares en otras tecnologías, guarda muchos datos que no se usan.
Por ejemplo, creo un tipo de dato para guardar «presupuestos». Hay unas pocas columnas que se rellenarán a NULL o con una cadena vacía aunque no se usen (por ejemplo porque no estemos usando el extracto o el contenido). Y bueno, ahí hay un problema, no el más grande, pero al menos uno.
La tabla postmeta
Aquí realmente es donde está el meollo de la cuestión. Aquí y en todo lo relacionado con los términos y sus relaciones, que ocupan multitud de registros. La tabla postmeta guarda todos los datos de productos, entradas, páginas o cualquier custom post type que usemos; que no «caben» en la tabla posts. Y si en su día aprendistéis que MySQL o MariaDB, la base de datos sobre la que se asienta WordPress, es relacional, os preguntaréis cómo hacerlo.
Así a bote pronto alguien podría pensar, en hacer un ALTER de la tabla cada vez. De forma que si voy a gestionar facturas y voy a guardar el dato «CIF del cliente», haré un ALTER y meteré una columna para poder hacerlo. Eso como podéis imaginar no es así. Imaginad que cada plugin o tema hiciera unos pocos ALTER sobre esa tabla, la realidad es que sería imposible de gestionar, inseguro y además muy poco eficaz.
La alternativa es usar una tabla con una estructura clave valor. De forma que tenemos cuatro columnas básicamente:
- un identificador para diferenciar cada fila de la tabla postmeta
- un identificador foráneo para identificar con qué registro de la tabla post, se relaciona este registro de meta
- la clave, es decir, el tipo de dato a guardar (en el caso anterior podría ser «cif_cliente»)
- el valor, lo que realmente quiere guardarse, en este caso por ejemplo «B00000000»
Como podéis imaginar si tenemos un registro con 40 datos asociados, que ya es exagerar pero cosas peores he visto, tendríamos:
- en una estructura relacional normal, un sólo registro con algo más de 40 columnas (las necesarias para guardar identificadores y demás)
- en WordPress, tendremos un registro de la tabla post, más o menos lleno; y luego aparte 40 registro de la tabla postmeta. Que encima al no ser el mismo registro e ir relacionados vía identificador, harán que todo vaya algo más lento
¿Y esto por qué se hace «así de mal»?
Tras contaros todo esto, pensaréis que esto es un desastre. Y bueno, según la versión que os he contado lo es. La realidad es diferente. Es cierto que de cara a rendimiento esto es más lento. Es innegable. Pero «a efecto prácticos y para muchos casos que no para todos», la pérdida de velocidad es más que asumible gracias a lo que se gana. Versatilidad. Si no existiera este sistema multitud de soluciones que se han desarrollado en este tiempo no podrían haberse implementado. Os podría decir nombres, como WooCommerce, como Contact Form 7, pero realmente podríamos decir que esta estructura es la que le da vida a WordPress.
Aparte, al estar todo guardado en las mismas tablas, las funciones de acceso y consulta de datos son siempre iguales y eso facilita la vida a los desarrolladores y se pueden ver mecanismos para optimizar dichos accesos.
Así que bueno, creo que todos estamos de acuerdo en que esta versatilidad es una de las bases del enorme éxito de WordPress.
Antes de terminar no quería sólo «culpar» a estas dos tablas de la lentitud en la consultas. Las tablas relacionadas con los term, tienen incluso más complejidad y generan también multitud de registros. Así que en efecto, también son culpables, pero volviendo a lo mismo de antes, son la base de toda la versatilidad que tenemos.