After reporting weirdness last week I finally sat down with a completely clean and virgin install of WordPress 2.3.2 and traced what happens when you make a permalink request for a non-existent URL.
Here are two sets of URLs to use as examples and context:
- These are valid URLs:
- These are _not_ valid URLs:
Valid URLs get parsed, the expected MySQL queries get executed, and the results are processed and returned to the browser. Normal. The problem is that invalid URLs that get sent through WordPress still result in a query like the following being executed on the database. What?
``` SELECT SQL_CALC_FOUND_ROWS test_posts.* FROM test_posts WHERE 1=1 AND post_type = 'post' AND (post_status = 'pub lish' OR post_status = 'private') ORDER BY post_date DESC LIMIT , 10 ``` |
That is, even after a URL is sent through WP->parse_request()
and found to be invalid/404, WordPress marches on to WP->query_posts()
and hits the database with a generic request for the X most recent posts. And because this is executed for every 404, it actually results in a lot of database activity.
In most cases MySQL has cached the result, and so it poses a minimal load on the server. And even if the cache is stale, for most sites it’s not a particularly resource intensive query.
But, if you’ve got 350,000 rows in the posts table, it’s incredibly resource intensive to order all those posts on the post_date
(datetime
) column. I’ve seen hundreds of them pile up and take forever to complete after writes to the table. It’s sufferable if write activity on the posts table is very low, but that’s not something I want to hope for.
So my question to the wp-hackers community is: Do we actually want to execute that query for every 404 under normal circumstances? If not, is the following (or something like it) the stupidest solution?
``` function query_posts() { global $wp_the_query; $this->build_query_string(); // return if the request URI is a 404 if( $this->did_permalink && $this->query_vars['error'] == '404' ) return; $wp_the_query->query($this->query_vars); } ``` |
The above works, but there’s probably a better way to write it.