WooCommercePerformance
11 min de leitura Maio 2025 Por Edinaldo Xavier

WooCommerce lento no banco de dados: como identificar queries pesadas antes de trocar de servidor

Tabela wp_options inflada, queries sem índice e postmeta mal estruturado degradam qualquer loja WooCommerce — como usar o MySQL slow query log e Query Monitor para encontrar o gargalo real.

Por que o banco de dados é frequentemente ignorado

Quando uma loja WooCommerce fica lenta, o instinto imediato é culpar o servidor. A primeira resposta de quase todo provedor de hospedagem é oferecer um upgrade de plano. Em muitos casos, isso resolve superficialmente — mas não elimina o problema real.

O que raramente é examinado é o banco de dados. E o banco de dados do WordPress/WooCommerce tem características estruturais que acumulam problemas ao longo do tempo: a arquitetura EAV do postmeta, a tabela wp_options que cresce sem controle, e queries que simplesmente nunca foram projetadas para escala.

Trocar de servidor sem resolver o problema de banco é como contratar um caminhão maior para entregar encomendas que estão sendo embaladas errado. O caminhão vai mais rápido, mas o problema de embalagem volta a aparecer.

Este artigo mostra como identificar os gargalos reais no banco antes de tomar qualquer decisão de infraestrutura.

wp_options inflada — o problema invisível

A tabela wp_options armazena configurações do WordPress, dados de plugins, transients, cache interno e metadados variados. O problema está na coluna autoload: toda linha marcada como autoload = yes é carregada em memória a cada request PHP, mesmo que o plugin que a criou não seja necessário naquela página.

Em lojas com 30, 40, 50 plugins ativos — e principalmente em lojas que já desinstalaram plugins sem limpeza adequada — a tabela wp_options pode ter centenas de milhares de registros com autoload ativado, somando megabytes de dados carregados desnecessariamente a cada pageview.

Para diagnosticar, execute diretamente no banco:

-- Total de dados com autoload ativo
SELECT SUM(LENGTH(option_value)) / 1024 / 1024 AS total_mb
FROM wp_options
WHERE autoload = 'yes';

-- Top 20 maiores entradas com autoload
SELECT option_name, LENGTH(option_value) / 1024 AS size_kb, autoload
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 20;

-- Contagem total de registros com autoload
SELECT COUNT(*) FROM wp_options WHERE autoload = 'yes';

Se o total de dados com autoload ultrapassar 1MB, você tem um problema. Valores acima de 5MB são críticos e explicam boa parte da lentidão genérica da loja.

Outra categoria de problema nessa tabela são os transients — dados temporários de cache que plugins escrevem e que deveriam ter prazo de validade. Muitos plugins criam transients e nunca os limpam adequadamente:

-- Contar transients expirados ainda na tabela
SELECT COUNT(*) FROM wp_options
WHERE option_name LIKE '_transient_%'
  AND option_name NOT LIKE '_transient_timeout_%';

A limpeza de transients expirados deve ser parte da rotina de manutenção. Via WP-CLI: wp transient delete --expired.

Como ativar e ler o slow query log no MySQL

O slow query log é a ferramenta mais direta para identificar queries problemáticas em produção. Ele registra todas as queries que excedem um tempo limite configurável, com detalhes de tempo de execução, número de linhas examinadas e o SQL completo.

Para ativar, adicione ao arquivo /etc/mysql/my.cnf (ou my.ini no Windows) na seção [mysqld]:

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
min_examined_row_limit = 100

O parâmetro log_queries_not_using_indexes é especialmente útil — ele captura queries sem índice mesmo que sejam rápidas agora, porque essas queries ficam cada vez mais lentas conforme a tabela cresce.

Após algumas horas (ou dias, se o tráfego for baixo), analise o log com mysqldumpslow:

# Top 10 queries por tempo acumulado total
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# Top 10 queries por pior tempo individual
mysqldumpslow -s at -t 10 /var/log/mysql/slow.log

# Filtrar apenas queries do WordPress (contêm wp_)
mysqldumpslow -s t /var/log/mysql/slow.log | grep wp_

As queries mais problemáticas em WooCommerce quase sempre envolvem: buscas em wp_postmeta sem índice em meta_value, JOINs entre wp_posts e wp_postmeta com múltiplos filtros, e SELECTs em wp_woocommerce_order_items com volume alto.

💡

Alternativa sem acesso ao servidor: Se você não tem acesso ao arquivo de configuração do MySQL, ative o slow log temporariamente via SQL com privilégios de SUPER: SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1;. Isso persiste até o próximo restart do MySQL.

Query Monitor — diagnóstico direto no WordPress

O plugin Query Monitor (gratuito, disponível no repositório oficial do WordPress) é a ferramenta mais prática para diagnosticar queries em tempo real sem precisar de acesso ao servidor.

Após instalar e ativar, um painel aparece na barra de admin com informações detalhadas sobre cada pageview:

  • Queries lentas: lista queries que excederam 0.05s (configurável)
  • Queries duplicadas: a mesma query sendo executada múltiplas vezes — sinal claro de problema N+1
  • Caller: qual plugin ou função PHP disparou cada query — essencial para rastrear a origem
  • Total de queries por página: páginas com mais de 50–100 queries merecem atenção

O que procurar especificamente no Query Monitor para WooCommerce:

  • Queries em wp_postmeta com WHERE meta_key = '...' sem índice composto em (post_id, meta_key)
  • Queries na listagem de pedidos (/wp-admin/edit.php?post_type=shop_order) com tempo elevado
  • Queries duplicadas disparadas por plugins de analytics, review ou chat
  • Queries com SELECT * em tabelas grandes — desperdiçam memória e I/O
⚠️

Remova o Query Monitor em produção após o diagnóstico. Ele adiciona overhead mensurável por coletar e formatar dados de todas as queries. Use em ambiente de staging ou em horários de baixo tráfego em produção.

postmeta e orderitemmeta — queries N+1 que travam a listagem

O modelo de dados do WordPress para pedidos WooCommerce é estruturalmente problemático em escala. Cada pedido é um post (wp_posts), e cada metadado do pedido (status, cliente, endereço, forma de pagamento, etc.) é uma linha separada em wp_postmeta.

Para exibir uma listagem de 20 pedidos no admin, o WooCommerce precisa:

  1. 1 query para buscar os 20 posts de pedido
  2. N queries para buscar os metadados de cada pedido (N+1 clássico)
  3. Queries adicionais para order items em wp_woocommerce_order_items
  4. Queries para order item meta em wp_woocommerce_order_itemmeta

Em lojas com milhares de pedidos, a listagem pode disparar 200–500 queries por pageview — completamente normal pela arquitetura, mas impraticável sem otimização.

A solução de longo prazo é migrar para o HPOS (High-Performance Order Storage), o novo sistema de armazenamento de pedidos do WooCommerce que usa tabelas dedicadas (wc_orders, wc_orders_meta) em vez do modelo postmeta. HPOS reduz drasticamente o número de queries e permite índices adequados:

# Verificar se HPOS está disponível e ativar via WP-CLI
wp option get woocommerce_feature_custom_order_tables_enabled
wp option update woocommerce_feature_custom_order_tables_enabled yes

Antes de migrar para HPOS em produção, verifique a compatibilidade de todos os plugins críticos no painel WooCommerce → Status → Ferramentas.

Índices ausentes — como identificar e criar sem derrubar produção

O MySQL pode sugerir índices ausentes através do EXPLAIN. Para qualquer query lenta identificada no slow log, execute:

EXPLAIN SELECT p.ID, p.post_status, pm.meta_value
FROM wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'shop_order'
  AND pm.meta_key = '_customer_user'
  AND pm.meta_value = '42';

Se o campo type mostrar ALL (full table scan) ou rows mostrar um número muito alto relativo ao resultado, é sinal de índice ausente. O campo Extra com Using filesort ou Using temporary indica ineficiência.

Para criar índices sem derrubar produção em MySQL 5.6+, use ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE:

-- Índice composto para buscas por meta_key + meta_value no postmeta
ALTER TABLE wp_postmeta
  ADD INDEX idx_meta_key_value (meta_key(20), meta_value(20))
  ALGORITHM=INPLACE, LOCK=NONE;

-- Índice para busca por tipo de post + status
ALTER TABLE wp_posts
  ADD INDEX idx_post_type_status (post_type, post_status)
  ALGORITHM=INPLACE, LOCK=NONE;

ALGORITHM=INPLACE, LOCK=NONE permite que a tabela continue disponível para leitura e escrita durante a criação do índice. Em tabelas grandes (milhões de registros), a operação pode levar minutos — monitore o progresso com SHOW PROCESSLIST.

Limpeza e manutenção preventiva

O banco de dados do WooCommerce precisa de manutenção periódica. As operações abaixo devem ser rotina — mensalmente em lojas pequenas, semanalmente em lojas com alto volume:

# Via WP-CLI — limpeza de revisões de posts
wp post delete $(wp post list --post_type='revision' --format=ids) --force

# Limpar transients expirados
wp transient delete --expired

# Otimizar tabelas (equivalente ao OPTIMIZE TABLE do MySQL)
wp db optimize

# Limpar carrinhos abandonados com mais de 7 dias
wp wc tool run clear_abandoned_carts --user=1

# Ver tamanho atual de cada tabela
wp db query "SELECT table_name, ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.TABLES WHERE table_schema = DATABASE() ORDER BY (data_length + index_length) DESC LIMIT 15;"

Para lojas que processam muitos pedidos, considere também arquivar pedidos antigos em uma tabela separada ou migrar para HPOS — a combinação das duas estratégias é o que diferencia lojas WooCommerce que escalam das que emperram no mesmo problema todo trimestre.

WooCommerce lento e você não sabe onde está o gargalo?

Faço diagnóstico completo de banco de dados WooCommerce: análise de slow queries, tamanho de wp_options, índices ausentes e viabilidade de migração para HPOS. Entrego um relatório priorizado com o que resolver primeiro.

WooCommerce ainda lento após trocar de servidor?

Se o problema não sumiu com o upgrade de hospedagem, é porque o gargalo está no banco. Diagnóstico técnico gratuito para identificar as queries que estão consumindo mais tempo.

🎯

Diagnóstico 100% gratuito

Análise prévia da sua loja sem custo.

Resposta em até 2 horas

Atendimento via WhatsApp em dias úteis.

🔒

Sem compromisso inicial

Proposta só se fizer sentido para os dois lados.