Wow. This blog has gotten a bit lopsided as of late on the MySQL side of stuff. A symptom of all the MySQL wizardry I’ve been doing and learning at my new job. I found out today that you can add multiple parameters/conditions to an INNER JOIN statement and I feel kind of dumb for not knowing this before. Using multiple parameters on your inner join you can remove the need for nasty sub queries!
Take this query for instance:
SELECT DISTINCT wp_posts.*, wp_users.user_nicename, ((SELECT meta_value FROM wp_postmeta meta WHERE meta.meta_key = 'views' AND meta.post_id = wp_posts.ID)*1) as views FROM article_to_categories INNER JOIN wp_posts ON wp_posts.ID = article_to_categories.wp_post_id INNER JOIN wp_users ON wp_users.ID = wp_posts.post_author WHERE article_to_categories.categories_id = $id ORDER BY views DESC
On a production server this query is sadly executing in 0.1 seconds. This is due almost entirely to that nasty little sub select in there. In my opinion, sub selects should be avoided at all cost. They are a symptom of at best an unoptimized query and at a worst a poorly designed database. Sometimes I’m a guilty party. Our goal is to get rid of the sub query:
SELECT meta_value FROM wp_postmeta meta WHERE meta.meta_key = 'views' AND meta.post_id = wp_posts.ID
We can do this by specifying multiple parameters and conditions on our join statement.
SELECT DISTINCT wp_posts.*, wp_users.user_nicename, (wp_postmeta.meta_value*1) as views FROM article_to_categories INNER JOIN wp_posts ON wp_posts.ID = article_to_categories.wp_post_id INNER JOIN wp_users ON wp_users.ID = wp_posts.post_author INNER JOIN wp_postmeta ON (wp_postmeta.post_id = wp_posts.ID AND wp_postmeta.meta_key = 'views') WHERE article_to_categories.categories_id = $id ORDER BY views DESC
Notice that when joining on wp_postmeta I specify that I want all records matching wp_posts.ID and that match the meta_key views. By moving away from the sub select I was able to trim the query execution time to 0.03 seconds. Thats a massive improvement especially for a query that is run in bulk!
INNER JOIN wp_postmeta ON (wp_postmeta.post_id = wp_posts.ID AND wp_postmeta.meta_key = 'views')
I’ve got a feeling I’ll need to go back through some of my older code and introduce some needed query optimizations. How about you?