Cada consulta cuenta: por qué el rendimiento de la base de datos es el cuello de botella oculto de tu tienda

He auditado más de 200 tiendas PrestaShop en los últimos cinco años. Cada vez—sin excepción—la mayor mejora de rendimiento viene de la capa de base de datos. No de un CDN. No de la compresión de imágenes. No de otro plugin de caché. La base de datos.

Monitorización del rendimiento del servidor para la optimización de consultas de base de datos PrestaShop

Una carga de página típica de PrestaShop ejecuta entre 80 y 300 consultas SQL. En una tienda con más de 10.000 productos, ese número puede superar las 500 en páginas de categoría con navegación por capas. Cuando incluso un puñado de esas consultas tarda 200ms en lugar de 2ms, tu Time to First Byte (TTFB) se dispara, la CPU de tu servidor se satura y tu tasa de conversión cae en picado. La propia investigación de Google muestra que un aumento de 100ms en el tiempo de carga reduce las conversiones hasta un 7%.

Este artículo no es una visión genérica de “cómo hacer PrestaShop más rápido”. Voy a profundizar en el rendimiento de la base de datos—identificar consultas lentas, entender planes de ejecución, ajustar InnoDB, elegir los índices adecuados y limpiar la acumulación de datos que silenciosamente mata tu tienda. Si ya has leído nuestra guía general de rendimiento, considera esto el siguiente capítulo.

Paso 1: Activar el registro de consultas lentas — Tu mejor herramienta de diagnóstico

Antes de optimizar nada, necesitas ver qué es realmente lento. El registro de consultas lentas de MySQL registra cada consulta que supera un umbral de tiempo que tú defines. He perdido la cuenta de cuántos propietarios de tiendas se saltan este paso y van directamente a “añadir Redis”—eso es como tomar analgésicos sin diagnosticar la lesión.

Activar el registro de consultas lentas

Añade estas líneas a tu archivo de configuración de MySQL o MariaDB (típicamente /etc/mysql/mysql.conf.d/mysqld.cnf o /etc/mysql/mariadb.conf.d/50-server.cnf):

# Enable slow query logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 0.5
log_queries_not_using_indexes = 1
min_examined_row_count = 100

Los ajustes clave:

  • long_query_time = 0.5 — Registra cualquier consulta que tarde más de 500ms. El valor por defecto de 10 segundos es absurdamente alto para comercio electrónico; cuando una consulta tarda 10 segundos, tu cliente se fue hace 8 segundos.
  • log_queries_not_using_indexes = 1 — Captura consultas que hacen escaneos completos de tabla aunque sean rápidas en conjuntos de datos pequeños. Estas son bombas de relojería que explotan cuando tu catálogo crece.
  • min_examined_row_count = 100 — Filtra consultas triviales para que tu registro se mantenga enfocado en problemas reales.

Después de activarlo, reinicia MySQL y deja que recopile datos durante al menos 24 horas cubriendo un ciclo completo de tráfico. Luego analiza:

# Summarize the worst offenders
mysqldumpslow -s t -t 20 /var/log/mysql/slow-query.log

# Or use pt-query-digest from Percona Toolkit for deeper analysis
pt-query-digest /var/log/mysql/slow-query.log > /tmp/query-report.txt

pt-query-digest del Percona Toolkit es el estándar de oro aquí. Agrupa consultas similares, las ordena por tiempo total de ejecución y te muestra exactamente dónde está gastando su vida tu base de datos. Instálalo—es gratuito y está disponible en la mayoría de los gestores de paquetes.

Paso 2: Leer planes EXPLAIN — La habilidad que separa adivinar de saber

Una vez que has identificado tus consultas lentas, el siguiente paso es entender por qué son lentas. El comando EXPLAIN de MySQL te muestra el plan de ejecución de la consulta—cómo decide el optimizador recuperar tus datos.

EXPLAIN SELECT p.id_product, pl.name, p.price
FROM ps_product p
LEFT JOIN ps_product_lang pl ON p.id_product = pl.id_product AND pl.id_lang = 1
LEFT JOIN ps_category_product cp ON p.id_product = cp.id_product
WHERE cp.id_category = 42 AND p.active = 1
ORDER BY p.date_add DESC;

Qué buscar en la salida

ColumnaSeñal de alarmaQué significa
typeALLEscaneo completo de tabla—MySQL lee cada fila. Solo aceptable en tablas pequeñas.
typeindexEscaneo completo de índice—mejor que ALL, pero sigue leyendo cada entrada del índice.
possible_keysNULLNo hay índices disponibles. El optimizador no tiene nada con lo que trabajar.
keyNULLNo se eligió ningún índice aunque existan opciones. Normalmente significa que las estadísticas del índice están desactualizadas.
rowsNúmero altoFilas estimadas examinadas. Compara con el conteo real de resultados—una proporción de 50.000:12 señala un índice faltante.
ExtraUsing temporaryMySQL crea una tabla temporal, a menudo desbordando a disco.
ExtraUsing filesortLos resultados se ordenan en memoria o en disco en lugar de mediante el orden del índice.

La salida ideal de EXPLAIN muestra type: ref o type: eq_ref, un key específico siendo utilizado y una estimación baja de rows. Cuando ves type: ALL combinado con Using temporary; Using filesort, has encontrado una consulta que está haciendo el máximo trabajo para resultados mínimos.

Un ejemplo real de PrestaShop

Una de las consultas lentas más comunes que encuentro en tiendas PrestaShop involucra la tabla ps_specific_price. En tiendas con miles de precios específicos (descuentos por cantidad, precios por grupo, promociones con rango de fechas), este patrón de consulta aparece constantemente en el registro lento:

EXPLAIN SELECT * FROM ps_specific_price
WHERE id_product = 1542
AND id_shop IN (0, 1)
AND id_currency IN (0, 1)
AND id_country IN (0, 8)
AND id_group IN (0, 1, 3)
AND id_customer = 0
AND from_quantity >= 1
AND (from = '0000-00-00 00:00:00' OR from <= NOW())
AND (to = '0000-00-00 00:00:00' OR to >= NOW());

En una tienda con más de 200.000 filas en specific_price, esta consulta examinaba 180.000 filas para devolver 3. La solución fue un índice compuesto:

ALTER TABLE ps_specific_price
ADD INDEX idx_product_shop_currency
(id_product, id_shop, id_currency, id_country);

Resultado: el tiempo de consulta bajó de 340ms a 0,8ms. En una página de categoría cargando 36 productos, ese único índice ahorró 12 segundos de tiempo de consulta acumulado por carga de página.

Paso 3: Las tablas más problemáticas de PrestaShop — Y cómo solucionarlas

Después de analizar registros de consultas lentas de docenas de tiendas, estas tablas son responsables de la mayoría de los problemas de rendimiento de la base de datos:

ps_connections y ps_connections_page

Estas tablas registran cada conexión de visitante y cada página que visualizan. En una tienda que recibe 5.000 visitantes diarios con una media de 4 páginas cada uno, son 20.000 filas por día—7,3 millones de filas por año. He visto tiendas con 50 millones de filas en ps_connections_page que nunca se habían limpiado.

-- Check the damage
SELECT table_name, table_rows,
  ROUND(data_length/1024/1024, 2) AS data_mb,
  ROUND(index_length/1024/1024, 2) AS index_mb
FROM information_schema.tables
WHERE table_schema = 'prestashop'
AND table_name IN ('ps_connections', 'ps_connections_page',
  'ps_log', 'ps_mail', 'ps_guest', 'ps_pagenotfound');

-- Clean old connection data (keep 90 days)
DELETE FROM ps_connections_page
WHERE id_connections IN (
  SELECT id_connections FROM ps_connections
  WHERE date_add < DATE_SUB(NOW(), INTERVAL 90 DAY)
);
DELETE FROM ps_connections WHERE date_add < DATE_SUB(NOW(), INTERVAL 90 DAY);

-- Clean old logs (keep 30 days)
DELETE FROM ps_log WHERE date_add < DATE_SUB(NOW(), INTERVAL 30 DAY);

-- Clean sent emails log (keep 60 days)
DELETE FROM ps_mail WHERE date_add < DATE_SUB(NOW(), INTERVAL 60 DAY);

-- Clean 404 tracking (keep 30 days)
DELETE FROM ps_pagenotfound WHERE date_add < DATE_SUB(NOW(), INTERVAL 30 DAY);

Importante: Después de eliminaciones grandes, recupera el espacio en disco:

OPTIMIZE TABLE ps_connections, ps_connections_page, ps_log, ps_mail, ps_guest;

ps_cart y ps_cart_product

Los carritos abandonados se acumulan para siempre. Una tienda de 5 años podría tener 2 millones de registros de carrito con 8 millones de filas de cart_product, el 95% de los cuales nunca convertirán. Limpia los carritos de más de 6 meses que no tengan un pedido asociado:

-- Identify orphan carts (no order placed)
DELETE cp FROM ps_cart_product cp
INNER JOIN ps_cart c ON cp.id_cart = c.id_cart
LEFT JOIN ps_orders o ON c.id_cart = o.id_cart
WHERE o.id_cart IS NULL
AND c.date_add < DATE_SUB(NOW(), INTERVAL 180 DAY);

DELETE c FROM ps_cart c
LEFT JOIN ps_orders o ON c.id_cart = o.id_cart
WHERE o.id_cart IS NULL
AND c.date_add < DATE_SUB(NOW(), INTERVAL 180 DAY);

ps_search_index y ps_search_word

El índice de búsqueda de productos puede crecer enormemente en catálogos grandes. Después de limpiar productos o actualizar en masa, reconstrúyelo:

-- Nuclear option: truncate and rebuild
TRUNCATE TABLE ps_search_index;
TRUNCATE TABLE ps_search_word;

-- Then trigger a full reindex via CLI:
php bin/console prestashop:search:reindex

Paso 4: Estrategia de índices para tablas de módulos de PrestaShop

Si desarrollas módulos—o usas módulos de terceros que crean tablas personalizadas—la indexación es tu responsabilidad. Las tablas del core de PrestaShop vienen con índices razonables, pero las tablas de módulos frecuentemente no tienen ninguno.

Principios para una indexación efectiva

  1. Indexa las columnas usadas en cláusulas WHERE — Si tu módulo consulta WHERE id_product = X AND id_shop = Y, crea un índice compuesto en (id_product, id_shop).
  2. El orden de las columnas importa en índices compuestos — Pon la columna más selectiva primero. Una columna con 10.000 valores únicos debería preceder a una con 3 valores únicos.
  3. Cubre tu ORDER BY — Si ordenas frecuentemente por date_add DESC, incluye date_add en el índice para evitar operaciones de filesort.
  4. No sobre-indexes — Cada índice ralentiza las operaciones INSERT y UPDATE. Para una tabla de escritura intensiva (como una tabla de registro), piénsalo bien antes de añadir índices.
-- Example: module review table with common query patterns
CREATE TABLE ps_mymodule_reviews (
  id_review INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  id_product INT UNSIGNED NOT NULL,
  id_customer INT UNSIGNED NOT NULL,
  id_shop INT UNSIGNED NOT NULL DEFAULT 1,
  rating TINYINT UNSIGNED NOT NULL,
  status TINYINT NOT NULL DEFAULT 0,
  date_add DATETIME NOT NULL,

  -- Composite index for "show approved reviews for product X"
  INDEX idx_product_status (id_product, status, date_add),

  -- Index for "show all reviews by customer"
  INDEX idx_customer (id_customer),

  -- Index for admin list with shop filter
  INDEX idx_shop_status (id_shop, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Encontrar índices faltantes en tablas existentes

-- List all module tables without non-primary indexes
SELECT t.table_name, t.table_rows
FROM information_schema.tables t
LEFT JOIN information_schema.statistics s
  ON t.table_name = s.table_name
  AND t.table_schema = s.table_schema
  AND s.index_name != 'PRIMARY'
WHERE t.table_schema = 'prestashop'
AND t.table_name LIKE 'ps_%'
AND t.table_rows > 1000
AND s.index_name IS NULL
ORDER BY t.table_rows DESC;

Esta consulta revela tablas con más de 1.000 filas y sin índices secundarios—candidatas principales para optimización.

Paso 5: Configuración de InnoDB — Los ajustes que realmente importan

InnoDB es el motor de almacenamiento de PrestaShop. Su configuración por defecto está diseñada para una carga de trabajo genérica en hardware modesto. Para un servidor de base de datos dedicado al comercio electrónico, necesitas ajustarlo.

Optimización de base de datos y configuración de caché de página completa para un PrestaShop más rápido

Los ajustes críticos

[mysqld]
# === Buffer Pool: The Single Most Important Setting ===
# Set to 70-80% of available RAM on a dedicated DB server.
# For shared hosting: 50% of RAM, minimum 1GB.
innodb_buffer_pool_size = 4G

# Split the buffer pool into instances (1 per GB)
innodb_buffer_pool_instances = 4

# === Log Files: Larger = Fewer Disk Writes ===
# Default 48M is too small. Set to 25% of buffer pool, max 2G each.
innodb_log_file_size = 1G
innodb_log_buffer_size = 64M

# === Flush Behavior ===
# 1 = Full ACID (safest, slower)
# 2 = Flush to OS buffer each commit, disk write once/sec (good compromise)
# 0 = Flush once/sec (fastest, risks 1 sec of data on crash)
innodb_flush_log_at_trx_commit = 2

# Use O_DIRECT to avoid double-buffering with OS page cache
innodb_flush_method = O_DIRECT

# === I/O Capacity ===
# SSD: 2000-4000. HDD: 200-400. Cloud SSD: 1000-2000.
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000

# === Thread Concurrency ===
innodb_read_io_threads = 4
innodb_write_io_threads = 4
innodb_purge_threads = 4

# === Per-Table Tablespace (default in MySQL 5.7+, verify it's on) ===
innodb_file_per_table = 1

# === Temp Tables ===
tmp_table_size = 64M
max_heap_table_size = 64M

# === Sort and Join Buffers (per-connection, don't over-allocate) ===
sort_buffer_size = 2M
join_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 1M

# === Connection Pool ===
max_connections = 200
thread_cache_size = 100

# === Table Cache ===
table_open_cache = 4000
table_definition_cache = 2000

# === Disable Performance Schema in Production (saves ~400MB RAM) ===
performance_schema = OFF

Entender innodb_buffer_pool_size

Este es el ajuste de MySQL más impactante para PrestaShop. El buffer pool es donde InnoDB cachea los datos de tabla e índices en memoria. Cuando una consulta necesita datos que ya están en el buffer pool, se sirven desde RAM en lugar de disco—órdenes de magnitud más rápido.

Cómo dimensionarlo:

-- Check your total database size
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_gb
FROM information_schema.tables
WHERE table_schema = 'prestashop';

-- Check buffer pool hit ratio (should be > 99%)
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';

-- Calculate: hit_ratio = 1 - (reads / read_requests) * 100
-- If below 99%, increase buffer_pool_size

Un benchmark real de las pruebas de Releem en MariaDB 10.5 con una tienda PrestaShop mostró que una configuración adecuada de InnoDB (buffer pool dimensionado a 3,2GB para una base de datos de 1GB) redujo el tiempo de respuesta un 39%—de 610ms a 370ms—y aumentó las consultas por segundo un 53%.

Query Cache: MariaDB vs MySQL 8

Este es un tema frecuentemente malinterpretado. MySQL 8.0 eliminó el query cache por completo. Oracle determinó que la contención de mutex del cache causaba más problemas de los que resolvía a escala. MariaDB, sin embargo, aún lo soporta y puede ayudar a tiendas PrestaShop con cargas de trabajo intensivas en lectura.

Para MariaDB (10.5+):

query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M

Para MySQL 8.0+: No intentes activarlo—no existe. En su lugar, confía en un buffer pool correctamente dimensionado y considera el caché a nivel de aplicación con Redis.

Si estás en MySQL 8 y consideras un cambio, MariaDB 10.11 es completamente compatible con PrestaShop y muchos proveedores de hosting lo ofrecen como reemplazo directo.

Paso 6: Patrones de consulta específicos de PrestaShop a vigilar

Más allá del ajuste general de MySQL, PrestaShop tiene patrones de consulta específicos que causan problemas de rendimiento a escala. Aquí están los que encuentro con más frecuencia:

El problema del conteo de productos

La navegación por capas de PrestaShop (búsqueda facetada) ejecuta consultas COUNT para cada combinación de filtros. En una categoría con 15 grupos de atributos y 200 atributos, esto puede generar más de 200 consultas COUNT individuales por carga de página. Cada consulta parece inocente:

SELECT COUNT(DISTINCT p.id_product)
FROM ps_product p
INNER JOIN ps_product_attribute_combination pac ...
WHERE ... AND pac.id_attribute = 47;

Pero 200 de ellas a 10ms cada una equivalen a 2 segundos de tiempo puro de consulta. La solución es usar una tabla de índice pre-calculada (que módulos como nuestros módulos de SEO y rendimiento pueden proporcionar) o reducir los filtros visibles mediante la configuración de categorías.

El problema de consultas N+1 en hooks de módulos

Un módulo registrado en displayProductListReviews que ejecuta una consulta por producto crea un problema N+1. Si tu página de categoría muestra 36 productos, son 36 consultas adicionales—por módulo:

// Bad: query per product in a list hook
public function hookDisplayProductListReviews($params) {
    $id_product = (int)$params['product']['id_product'];
    $result = Db::getInstance()->getRow(
        'SELECT AVG(rating) as avg_rating
         FROM ps_mymodule_reviews
         WHERE id_product = ' . $id_product
    );
    // ...
}

// Good: batch query all products at once, cache the result
public function hookActionProductSearchAfter($params) {
    $products = $params['result']->getProducts();
    $ids = array_column($products, 'id_product');

    $ratings = Db::getInstance()->executeS(
        'SELECT id_product, AVG(rating) as avg_rating
         FROM ps_mymodule_reviews
         WHERE id_product IN (' . implode(',', array_map('intval', $ids)) . ')
         GROUP BY id_product'
    );
    // Store in static cache for use in display hook
}

Evaluación de reglas de carrito

Las tiendas con cientos de reglas de carrito activas sufren en cada carga de la página del carrito. Las condiciones de cada regla de carrito (restricciones de producto, restricciones de categoría, grupos de clientes) activan consultas separadas. Si tienes más de 50 reglas de carrito activas, considera:

  • Archivar las reglas expiradas (establece su active a 0 y date_to a una fecha pasada)
  • Consolidar reglas superpuestas donde sea posible
  • Añadir un índice en ps_cart_rule.active, ps_cart_rule.date_from, ps_cart_rule.date_to

Paso 7: Monitorización en producción — No lo configures y te olvides

El ajuste de base de datos no es una tarea de una sola vez. Los datos de tu tienda crecen, los patrones de tráfico cambian y las actualizaciones de módulos pueden introducir nuevos patrones de consulta. Configura una monitorización continua:

Métricas esenciales a rastrear

-- Buffer pool efficiency (check weekly)
SELECT
  FORMAT(VARIABLE_VALUE, 0) AS buffer_pool_read_requests
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests';

-- Slow queries per hour (should trend downward)
SHOW GLOBAL STATUS LIKE 'Slow_queries';

-- Table lock waits (should be near zero for InnoDB)
SHOW GLOBAL STATUS LIKE 'Table_locks_waited';

-- Temporary tables created on disk (high = increase tmp_table_size)
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
SHOW GLOBAL STATUS LIKE 'Created_tmp_tables';

-- Thread connection usage
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';

Monitorización automatizada

Para tiendas donde el tiempo de inactividad significa pérdida real de ingresos, considera estas soluciones de monitorización:

  • Percona Monitoring and Management (PMM) — Gratuito, de código abierto, dashboards completos de MySQL/MariaDB con analítica de consultas. Es lo que uso para todas las tiendas de clientes.
  • Releem — Ajuste automatizado de MySQL que adapta los parámetros basándose en tu carga de trabajo real. Útil si no quieres ajustar manualmente el my.cnf.
  • MySQLTuner — Un script Perl que proporciona recomendaciones rápidas: perl mysqltuner.pl --host 127.0.0.1

Paso 8: Cuándo añadir Redis — Y qué resuelve realmente

Redis no es un sustituto de la optimización de base de datos. Es una capa adicional. Si tus consultas subyacentes son lentas, Redis enmascara el problema para las peticiones cacheadas y lo empeora cuando el caché expira (thundering herd).

Después de que hayas optimizado tus índices, limpiado tus tablas y ajustado InnoDB—entonces añade Redis para:

  • Almacenamiento de sesiones — Elimina el bloqueo de archivos bajo peticiones concurrentes. Configúralo en config/defines.inc.php o usa el manejador de sesiones de Symfony.
  • Caché de Smarty — Evita que Smarty escriba miles de archivos de plantillas compiladas en disco.
  • Caché de Symfony — Metadatos de Doctrine, enrutamiento y cachés del contenedor de servicios servidos desde memoria.
  • Caché a nivel de módulo — Cualquier dato de módulo que sea costoso de calcular pero que cambie con poca frecuencia.

El resultado: en una tienda correctamente ajustada, añadir Redis típicamente reduce el TTFB entre un 30 y un 50% adicional. Nuestra guía de rendimiento cubre la configuración de Redis en detalle.

Paso 9: Full Page Cache — La última capa

Una vez que tu base de datos está limpia y tu caché de aplicación está en Redis, la optimización definitiva es eliminar la ejecución de PHP completamente para los visitantes anónimos. Varnish o nginx FastCGI cache pueden servir una página completamente renderizada en menos de 10ms—comparado con 200-500ms para una página renderizada por PHP.

El desafío con PrestaShop es la invalidación del caché. Los cambios de precio, actualizaciones de stock, inicio/fin de promociones y modificaciones del carrito requieren:

  • Invalidación basada en etiquetas — El módulo xkey de Varnish te permite etiquetar páginas cacheadas por producto, categoría o página CMS y purgarlas selectivamente.
  • Enfoque basado en TTL — Cachear páginas durante 5-15 minutos y aceptar una breve obsolescencia. Adecuado para la mayoría de las tiendas donde la precisión del stock al segundo no es crítica.
  • Enfoque híbrido — Cachear la estructura de la página, usar ESI (Edge Side Includes) o JavaScript para fragmentos dinámicos como el widget del carrito y el estado de login.

Para tiendas con alto tráfico, la combinación de base de datos optimizada + caché de aplicación Redis + FPC Varnish rutinariamente alcanza un TTFB inferior a 50ms. Uno de nuestros clientes con un catálogo de 15.000 productos pasó de 800ms de TTFB a 120ms usando exactamente esta pila.

El orden de prioridad: máximo impacto, mínimo riesgo

Si te llevas una sola cosa de este artículo, es esta lista de prioridades:

  1. Activar el registro de consultas lentas y corregir las 10 principales consultas — Impacto inmediato, coste cero, sin riesgo.
  2. Limpiar tablas hinchadasps_connections, ps_log, ps_mail, carritos abandonados. Recuperación instantánea de espacio y rendimiento.
  3. Ajustar el buffer pool de InnoDB — Un cambio de configuración en my.cnf, impacto masivo.
  4. Añadir índices faltantes en tablas de módulos — Alto impacto si usas módulos con muchos datos.
  5. Añadir Redis para sesiones y caché — Suelo de rendimiento fiable, elimina el cuello de botella de E/S de archivos.
  6. Implementar full page cache — El multiplicador final para tiendas con alto tráfico.

Cada paso se construye sobre el anterior. Saltar al paso 6 sin hacer los pasos 1-4 es construir sobre cimientos inestables.

Si no estás seguro de dónde se encuentra tu tienda, empieza con el registro de consultas lentas. Veinticuatro horas de datos te dirán más que cualquier plugin de rendimiento. Y si necesitas ayuda para interpretar lo que encuentras, contáctanos—el análisis de rendimiento de base de datos es una de las cosas que mejor hacemos.

David Miller construye herramientas de rendimiento para PrestaShop y lleva optimizando bases de datos de comercio electrónico desde 2017. Sus módulos están disponibles en mypresta.rocks.

Compartir esta publicación:
David Miller

David Miller

Más de una década de experiencia práctica con PrestaShop. David desarrolla módulos de comercio electrónico de alto rendimiento centrados en SEO, optimización del checkout y gestión de tiendas. Apasionado por el código limpio y los resultados medibles.

¿Te gustó este artículo?

Recibe nuestros últimos consejos, guías y actualizaciones de módulos en tu bandeja de entrada.

Comentarios (3)

P
Piotr Nowak 14/02/2026
Good article but I think you should mention the opcache preloading feature for PHP 8.1+. It made a big difference for us combined with the query optimizations you described.
Responder
L
Laura Bianchi 14/02/2026
Implemented the Redis full page cache approach you described here. Our TTFB went from 800ms to 120ms. Incredible difference for our catalog of 15k products.
Responder
D
David Miller 14/02/2026
Amazing results Laura! Redis FPC is a game changer especially for large catalogs. If you want to squeeze even more out of it, try combining it with Varnish as a reverse proxy.
Cargando...
Volver arriba