Есть ли способ установить псевдоним для аргументов meta_query при запуске get_posts()
? Один из моих запросов работает плохо. Для оптимизации мне просто нужно иметь возможность повторно использовать одну и ту же объединенную таблицу вместо объединения в 3 таблицы, когда нужна только одна.
Мой текущий пример ...
$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);
что в основном переводит на это в прямом SQL ...
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;
Тем не менее, это добавление 2 дополнительных объединений для пользовательского мета-поля, abc_type
и, как следствие, эта производительность получила большой успех. Есть ли способ иметь возможность ссылаться на один и тот же псевдоним для нескольких аргументов meta_query? По сути, mt1
и mt3
они совершенно не нужны, я должен просто ссылаться на первую postmeta
таблицу, которая используется с первой ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. Или, по крайней мере, если я могу установить собственный псевдоним для каждого из них, я мог бы сослаться на это.
Более оптимальный запрос будет ...
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;
Мысли?
источник
get_posts()
.posts_where
Фильтр может быть полезным.Ответы:
Посмотрите на
meta_query_find_compatible_table_alias
фильтр, определенный вwp-includes/class-wp-meta-query.php
. Документация этого фильтра:Вполне вероятно, что вызывающая функция
find_compatible_table_alias
возвращает false, и поэтому запрос создаетmt*
псевдонимы. Вот пример кода, использующего этот фильтр, хотя я лично рекомендовал бы кое-что, что немного легче понять. Подобные изменения запросов могут привести к множеству головных болей в будущем, и вообще может быть неочевидно, где запрос испортится, особенно если вы привлечете других разработчиков в будущем. Это сказал ...Это приводит к запросу как
источник
Вы можете использовать
posts_where
иposts_join
фильтры для изменения запроса. Это не очень элегантно, но вы должны иметь возможность возиться с этими двумя фильтрами, чтобы ваш sql был более оптимизирован. Это грубо, но я не вижу лучшего способа в классе WP_Query. Это не значит, что нет.Там должно быть несколько проверок, чтобы случайно не изменить другие запросы. Это оставлено в качестве упражнения для читателя.
источник
Вы можете оптимизировать свой запрос, удалив первый мета-запрос, так как он избыточен, например:
Таким образом, вы получите только либо,
pink puppy
либоlarge kitten
, как вы думаете, я полагаю.Что касается оптимизации внутренних MySQL-запросов WordPress, я полагаю, что вам следует избегать этого, поскольку вы подвергаете себя возможным побочным эффектам. Вы бы лучше полагались на тот факт, что запросы кэшируются и выполняли бы некоторую дополнительную обработку PHP для (большего) набора данных. Я считаю, что это приведет к повышению общей производительности, поскольку узким местом является не количество данных, которые вы извлекаете из базы данных, а сложность, с которой они собираются (сколько запросов). PHP довольно быстро работает с массивами.
Поэтому я полагаю, что такая ситуация быстрее, учитывая, что мета поста кэшируется:
источник
Я на самом деле не парень в базе данных, но однажды я играл его по телевизору ...
Не эта часть
лучше заменить на
Вероятно, это можно упростить еще больше ... с некоторым псевдонимом, который застрял там в нужном месте, чтобы вы могли использовать оставшуюся часть запроса.
Просто мысль...
источник
get_posts()
, поэтому он сам не пишет запрос.