Gibt es eine Möglichkeit, einen Alias für die Argumente meta_query festzulegen, wenn a ausgeführt wird get_posts()
? Eine meiner Fragen ist schlecht. Zur Optimierung muss ich nur in der Lage sein, dieselbe verknüpfte Tabelle wiederzuverwenden, anstatt 3 Tabellen zu verbinden, wenn nur eine benötigt wird.
Mein aktuelles Beispiel ...
$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);
was sich im Grunde genommen in reinem SQL übersetzt ...
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;
Dies bedeutet jedoch, dass 2 zusätzliche Joins für das benutzerdefinierte Metafeld hinzugefügt werden abc_type
und die Leistung daher einen großen Erfolg hat. Gibt es eine Möglichkeit, denselben Alias für mehrere meta_query-Argumente zu referenzieren? Grundsätzlich mt1
und mt3
völlig unnötig, sollte ich nur in der Lage sein, auf die erste postmeta
Tabelle zu verweisen , die mit der ersten verwendet wird ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. Oder zumindest, wenn ich für jeden einen benutzerdefinierten Alias festlegen kann, könnte ich darauf verweisen.
Eine optimalere Abfrage wäre ...
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;
Gedanken?
quelle
get_posts()
.posts_where
Filter könnte nützlich sein.Antworten:
Schauen Sie sich den in
meta_query_find_compatible_table_alias
definierten Filter anwp-includes/class-wp-meta-query.php
. Dokumentation dieses Filters:Es ist wahrscheinlich, dass die aufrufende Funktion
find_compatible_table_alias
false zurückgibt und die Abfrage daher diemt*
Aliase erstellt. Hier ist ein Beispielcode, der diesen Filter verwendet, obwohl ich persönlich für etwas eintreten würde, das etwas einfacher zu verstehen ist. Das Ändern solcher Abfragen kann später zu Unmengen von Kopfschmerzen führen, und es ist möglicherweise überhaupt nicht ersichtlich, wo die Abfrage durcheinander gebracht wird, insbesondere wenn Sie in Zukunft andere Entwickler hinzuziehen. Das gesagt...Dies führt zu einer Abfrage wie
quelle
Mit den Filtern
posts_where
und können Sieposts_join
die Abfrage ändern. Es ist nicht sehr elegant, aber Sie sollten in der Lage sein, mit diesen beiden Filtern zu spielen, damit Ihr SQL optimiert wird. Es ist ein bisschen brutal, aber ich kann keinen besseren Weg in der WP_Query-Klasse sehen. Das heißt aber nicht, dass es das nicht gibt.Es sollte wahrscheinlich einige Überprüfungen geben, damit Sie nicht versehentlich andere Abfragen ändern. Das bleibt als Übung für den Leser.
quelle
Sie können Ihre Abfrage optimieren, indem Sie die erste Metaabfrage entfernen, da sie redundant ist.
Auf diese Weise erhalten Sie nur entweder
pink puppy
oderlarge kitten
, wie Sie beabsichtigen, glaube ich.Ich bin der Meinung, dass Sie sich bei der Optimierung der internen MySQL-Abfragen von WordPress davon fernhalten sollten, da Sie sich möglichen Nebenwirkungen aussetzen würden. Sie sollten sich besser darauf verlassen, dass Abfragen zwischengespeichert werden und mehr PHP-Verarbeitung für den (größeren) Datensatz durchführen. Ich glaube, dies wird insgesamt zu einer besseren Leistung führen, da der Engpass nicht die Datenmenge ist, die Sie aus der Datenbank extrahieren, sondern die Schwierigkeit, mit der sie erfasst werden (wie viele Abfragen). PHP kommt ziemlich schnell durch Arrays.
Daher glaube ich, dass eine solche Situation schneller ist, wenn man bedenkt, dass das Post-Meta zwischengespeichert wird:
quelle
Ich bin nicht wirklich ein Datenbank-Typ, aber ich habe einmal einen im Fernsehen gespielt ...
Würde das nicht Teil
besser ersetzt werden durch
Das könnte wahrscheinlich noch weiter vereinfacht werden. Mit einigen Alias, die an der richtigen Stelle gespeichert sind, können Sie den Rest Ihrer Abfrage verwenden.
Nur ein Gedanke...
quelle
get_posts()
, also schreibt er die Abfrage nicht selbst.