[wp-trac] [WordPress Trac] #38173: Meta query creates unecessary multiple left joins when using the same meta key
WordPress Trac
noreply at wordpress.org
Fri Feb 17 03:06:47 UTC 2017
#38173: Meta query creates unecessary multiple left joins when using the same meta
key
-------------------------+-----------------------------
Reporter: neonWired | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Future Release
Component: Query | Version: 3.2
Severity: normal | Resolution:
Keywords: needs-patch | Focuses: performance
-------------------------+-----------------------------
Changes (by boonebgorges):
* keywords: => needs-patch
* type: defect (bug) => enhancement
* version: 4.6 => 3.2
* component: Database => Query
* milestone: Awaiting Review => Future Release
Comment:
> Bug was registered 6 months ago and no one care about this?
There are many open enhancement requests in WordPress, and many of them
are worthwhile, but there are only so many people reviewing and writing
patches.
@neonWired is correct that no table join is required for subclauses that
are joined by `OR` that both operate on the same `meta_key` when one of
them uses the compare operator `NOT EXISTS`. But this syntax requires that
the `meta_key` comparison be put into the `ON` clause for that particular
`JOIN` clause. This already happens for `NOT EXISTS`:
https://core.trac.wordpress.org/browser/tags/4.7.2/src/wp-includes/class-
wp-meta-query.php#L536 But the logic becomes a good deal more complicated
when other clauses share a `JOIN` with a `NOT EXISTS` clause, because of
the order in which `WP_Meta_Query` currently builds SQL. Take @neonWired's
query as an example. Here's what happens internally:
1. SQL is generated for the first subclause (`'compare' => '!='`). The
JOIN clause looks like `INNER JOIN wp_postmeta ON ( wp_posts.ID =
wp_postmeta.post_id )`
2. SQL is generated for the second subclause after this. `WP_Meta_Query`
realizes it's a 'NOT EXISTS', so it knows that the JOIN clause must be
like `LEFT JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id AND
wp_postmeta.meta_key = 'product' )`
3. But in order to share the table join with the clause generated in 1,
we'd have to go back and modify the SQL that's already generated there, so
that it has the proper JOIN syntax.
SQL generation for clauses is more or less linear at the moment; there's
no easy way to jump back and change the syntax of a clause that already
been generated. We'd need to either (a) change the way that the clauses
are generated so that it's easier to change existing clauses, or (b)
create some sort of look-ahead device that can tell whether there's going
to be a 'NOT EXISTS' clause involved, and if so, process it first.
Either of these is quite possible, but it's not a trivial task. I've just
spent an hour or so trying to come up with a proof-of-concept, but I
haven't been successful. If anyone would like to have a go at writing a
patch, I'd be happy to help to review it.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/38173#comment:3>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list