
A listagem do seu custom post type com meta_query rodava em 200 ms e hoje leva oito segundos. No slow query log é sempre a mesma coisa: JOIN em wp_postmeta varrendo dezenas de milhares de linhas. O motivo está no esquema do WordPress: o índice padrão é KEY meta_key (meta_key(191)), e meta_value fica de fora.
Não adivinhe o SQL: pegue o que o WP_Query montou. Salve num arquivo com a tag de abertura do PHP — sem ela o eval-file só imprime o texto:
<?php
$q = new WP_Query([
'post_type' => 'imovel',
'posts_per_page' => 12,
'meta_query' => [['key' => 'cidade', 'value' => 'Curitiba']],
]);
echo $q->request;
# sudo -u www-data wp eval-file /tmp/q.php Copie a saída, ponha EXPLAIN na frente e rode com sudo -u www-data wp db query. Na linha de wp_postmeta o key vem como meta_key, com número gordo em rows e “Using where”: o MySQL pega toda linha cuja meta_key é cidade e só depois compara o valor, uma a uma.
ALTER TABLE wp_postmeta
ADD INDEX meta_key_value (meta_key(191), meta_value(20)),
ALGORITHM=INPLACE, LOCK=NONE; Os 191 caracteres são o mesmo prefixo que o núcleo já usa em meta_key, e vinte de meta_value bastam para separar os candidatos antes da comparação final. O ALGORITHM=INPLACE com LOCK=NONE mantém a tabela gravável durante a criação, mas só no InnoDB: em MyISAM o MySQL copia a tabela e trava escrita o tempo todo. Confira a engine e tenha um dump antes.
Índice não é de graça. wp_postmeta é a tabela mais escrita num WordPress com campos customizados, e agora todo INSERT mantém mais um índice: importação de catálogo e cron que grava meta em massa ficam mais lentos. Meça:
SELECT ROUND(data_length/1048576) AS dados_mb, ROUND(index_length/1048576) AS indice_mb
FROM information_schema.TABLES
WHERE table_schema = DATABASE() AND table_name = 'wp_postmeta'; E não espere milagre em ordenação: prefixo de índice não ordena nada. Se a meta é numérica e o orderby usa meta_value_num, o ganho é pequeno; aí o caminho é tirar o campo quente do postmeta para uma coluna própria.
Post com Perdeu o agendamento e backup que não roda há dias: inspecione a fila do WP-Cron, apague a trava…
Como aposentar o plugin AMP sem transformar centenas de URLs /amp/ indexadas em 404: o rewrite 301 no nginx, a…
A loja cai com OOM command not allowed when used memory > maxmemory: ajuste a maxmemory-policy do Redis e separe…
Adicione a caixa de aceite no checkout do WooCommerce e grave data e versão da política como meta do pedido,…
A função json_validate do PHP 8.3 diz se a string é JSON válido sem montar array nem objeto. Serve para…
Tire a chave de API do código com variável de ambiente, bloqueie o .env no nginx e entenda por que…