Existe uma maneira de definir um alias nos argumentos meta_query ao executar um get_posts()
? Uma das minhas consultas está com um desempenho ruim. Para otimizar, só preciso reutilizar a mesma tabela unida em vez de ingressar em 3 tabelas quando apenas uma é necessária.
Meu exemplo atual ...
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => array('puppy', 'kitten'),
'compare' => 'IN',
),
array(
'relation' => 'OR',
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'puppy',
'compare' => '=',
),
array(
'key' => 'abc_color',
'value' => 'pink',
'compare' => '=',
),
),
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'kitten',
'compare' => '=',
),
array(
'key' => 'abc_size',
'value' => 'large',
'compare' => '=',
),
),
),
)
);
get_posts($args);
que basicamente se traduz em SQL direto ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
INNER JOIN postmeta AS mt3 ON ( posts.ID = mt3.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( mt1.meta_key = 'abc_type' AND mt1.meta_value = 'puppy' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value > 'pink' )
)
OR
(
( mt3.meta_key = 'abc_type' AND mt3.meta_value = 'kitten' )
AND
( mt4.meta_key = 'abc_size' AND mt4.meta_value = 'large' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
No entanto, isso inclui 2 junções extras para o meta campo personalizado abc_type
e, como tal, o desempenho teve um grande sucesso. Existe uma maneira de poder fazer referência ao mesmo alias para vários argumentos meta_query? Basicamente, mt1
emt3
são totalmente desnecessários, eu deveria ser capaz de fazer referência à primeira postmeta
tabela usada com a primeira ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. Ou, pelo menos, se eu puder definir um alias personalizado em cada um deles, eu poderia fazer referência a isso.
Uma consulta mais ideal seria ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'puppy' )
AND
( mt1.meta_key = 'abc_color' AND mt1.meta_value > 'pink' )
)
OR
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'kitten' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value = 'green' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
Pensamentos?
fonte
get_posts()
.posts_where
filtro pode ser útil.Respostas:
Dê uma olhada no
meta_query_find_compatible_table_alias
filtro definido emwp-includes/class-wp-meta-query.php
. A documentação deste filtro:É provável que a função de chamada,,
find_compatible_table_alias
esteja retornando false e, portanto, a consulta crie osmt*
aliases. Aqui está um exemplo de código usando esse filtro, embora eu pessoalmente defenda algo que seja um pouco mais fácil de entender. Modificar consultas como essa pode levar a muitas dores de cabeça no caminho e pode não ser aparente em todos os lugares onde a consulta está sendo confusa, especialmente se você chamar outros desenvolvedores no futuro. Dito isto...Isso resulta em uma consulta como
fonte
Você pode usar os filtros
posts_where
eposts_join
para modificar a consulta. Não é muito elegante, mas você poderá mexer com esses dois filtros para que seu sql seja mais otimizado. É meio brutal, mas não consigo ver uma maneira melhor na classe WP_Query. Isso não está dizendo que não há.Provavelmente, deve haver algumas verificações para que você não modifique acidentalmente outras consultas. Isso é deixado como um exercício para o leitor.
fonte
Você pode otimizar sua consulta removendo a primeira meta consulta, pois ela é redundante, da seguinte forma:
Dessa forma, você só receberá um
pink puppy
oularge kitten
, como pretende, acredito.Quanto à otimização das consultas internas do MySQL do WordPress, acredito que você deve ficar longe disso, pois se exporia a possíveis efeitos colaterais. É melhor confiar no fato de que as consultas são armazenadas em cache e fazer um pouco mais de processamento PHP no conjunto de dados (maior). Acredito que isso levará a um melhor desempenho geral, pois o gargalo não é a quantidade de dados que você está extraindo do banco de dados, mas a dificuldade com a qual eles são coletados (quantas consultas). O PHP é bastante rápido como se fosse através de matrizes.
Então, acredito que uma situação como essa é mais rápida, considerando que a meta meta é armazenada em cache:
fonte
Eu não sou realmente um cara de banco de dados, mas joguei um na TV uma vez ...
Esta parte não
ser melhor substituído por
Isso provavelmente poderia ser simplificado ainda mais ... com alguns apelidos presos no local apropriado para que você possa usar o restante da sua consulta.
Apenas um pensamento...
fonte
get_posts()
, então ele não está escrevendo a consulta.