Memo: Avoid Nested Queries in MySQL at all costs

Some of my readers may be aware that nested subqueries such as “SELECT * FROM widgets WHERE id IN (SELECT …)”, don’t work all that well in MYSQL. While the syntax is usually correct, the performance issues in practice can be horrendous. This article delves deeper into this issue, and why MySQL performs so poorly with nested subqueries, but not so deep as to drive us all crazy.

Nested Queries

Background

The first complex query I learned how to write was a nested subquery, or just nested query for short. At the time I was learning SQL and databases, it was the simple and most obvious of all the complex queries/joins: Find a set of records whose Id is in a list of outputs of another query.

SELECT id,name,price 
FROM widgets 
WHERE id IN (SELECT DISTINCT widgetId FROM widgetOrders)

In the example above, we first query the widgetOrders table for all unique widgets that have been sold based on widgetId (the DISTINCT doesn’t change the output of the query, but can help performance). After we have such a list, we select the id, name, and price of those widgets using data from the widget table.

First off, why do people like nested queries? As I said, they are pretty easy to understand, ESPECIALLY for non-programmers. But what are the alternatives to nested queries? Joins! Non-programmers (and even some programmers) find joins to be mystifying and scary things. Words like INNER JOIN, RIGHT OUTER JOIN, or even the shortcut symbols *= scare a lot of people. For example, the previous query can be rewritten as an INNER JOIN as follows:

SELECT DISTINCT w.id,w.name,w.price 
FROM widgets w 
INNER JOIN widgetOrders o ON w.id=o.widgetId

So why is this scarier? First, while aliases like ‘w’ and ‘o’ for table names were previously optional, they become almost required with complex joins, since we’re essentially mixing a two level query into a single level. Also, we have to add new syntax such as INNER JOIN … ON. There’s a lot more going on, and a lot more for beginners to pick up and/or be scared off by.

Why nested joins are bad in theory

The first big question of this article revolves around how query optimizers work. You can write a query a thousand different ways that would all output the same information and might seem equivalent to you, but query optimizers are just not that smart. The search space they have to cover to effectively optimize a query is massive, longer than could ever be searched in a reasonable amount of time. Therefore, query optimizes are often collections of greedy algorithims. Sure, they will do intelligent things when they can figure them out in time, but often they just look for the ‘quick path out’ using some simple heuristics. If a query optimizer thinks a particular plan may be the fastest, it won’t necessarily spend time verifying it; it will just act. Because of this, it is very easy to trip up or hinder a query optimizer.

This brings us to nested queries. Even the best query optimizers in the best database software available have trouble with nested queries. This is because they often cannot optimize them in any reasonable manner. As we saw in the example, I took two separate queries and merged them into one. Most query optimizers are not smart enough to do this since finding such a conversion would take too long, or in computing terms would require too large a search space and near-infinite time. In fact, many query optimizers will flat out refuse to optimize nested queries if it sees them. Therefore, a general rule of thumb is to avoid nested queries as much as possible since you are essentially blocking the query optimizer from touching that part of the query. You should stick with more traditional joins as much as possible since this encourages the query optimizer to find better query paths.

Why nested joins are really bad in MySQL

While nested queries may have been the first type of complex query I worked with, I never had serious problems with them and never spent hours reworking them to non-nested queries, until I started working in MySQL. Many nested queries you might easily write are capable of completely grinding your MySQL database to a halt under certain data conditions. MySQL has posted a list of excuses and tips (to fix your queries instead of their code) and there’s numerous forums posts, blogs, bug reports, and articles discussing the issue, but I’ll streamline it for you: MySQL does terrible things when handling nested subqueries; therefore, if you are using MySQL they should be avoided at all costs.

Note: This does not mean you should avoid the IN or NOT IN syntax, for example “WHERE id IN (1,2,3)” is just fine. The problems is when “1,2,3” is replaced with a subquery such as “SELECT …”.

But Scott, I need a nested query!

If you absolutely need a nested query, you can always perform two distinct queries in your application as such:

Set X = CallDatabase("SELECT DISTINCT widgetId FROM widgetOrders");
CallDatabase("SELECT id,name,price FROM widgets WHERE id IN ("+X+")");

As strange as it sounds to recommend two database calls over one, there are many real cases in MySQL where this will perform better than nested queries.

The Future

The problem with nested queries is that in many circumstances they will perform just fine, but change the data slightly and they can seriously harm database performance in MySQL. For example, strange things can happen if the subquery returns no records so that you end up with “WHERE id IN ()”. Many of the issues with subqueries have been logged as bug on MySQL’s support site, so it’s possible in future versions they will be safer to use. For now though, avoid them as long as you program with MySQL, lest you want to create headaches for yourself down the road.

what is mentoring?

What is mentoring?  Listening?  Advising?  Helping?  I was looking for the definition of mentoring today and came across some interesting things.

dictionary.com lists two definitions:

1, a wise and trusted counselor or teacher.

2. an influential senior sponsor or supporter

These are both correct, but not very helpful to me.  Sometime later I came across an article that really expresses what I was looking for.

Mentoring is about one person helping another to achieve something. More specifically, something that is important to them. It is about giving help and support in a non-threatening way, in a manner that the recipient will appreciate and value and that will empower them to move forward with confidence towards what they want to achieve. Mentoring is also concerned with creating an informal environment in which one person can feel encouraged to discuss their needs and circumstances openly and in confidence with another person who is in a position to be of positive help to them

Parts of this initial paragraph really jump out at me.  I’ve listed the relevant keywords and phrases here with my thoughts on them from both being a formal/informal mentor/mentee:

  • helping – Why am I not surprised the first verb in the description is so critical?  Mentoring really does boil down to helping someone else.  The mentee is still responsible for themselves and everything pertaining to the situation.  Whereas the mentor gives advice/opinions/guidance to help the person.
  • achieve something – The goal might or might not be known to the mentee.  Sometimes there is a specific issue that one wants to discuss.   In that case there is a pretty clear goal.  Sometimes it’s just to hear advice on what is coming.  This is kind of vague.  For example, technical people are known for needing to improve their soft skills.  Yet we don’t tend to seek out advice on the topic.  A good mentor will bring it up anyway helping the person at least realize there is an opportunity out there.
  • non-threatening way – This should go without saying.  The idea of mentoring is to be guidance not “do this or else.”
  • appreciate and value – I found this phrase particularly interesting.  Usually I appreciate and value my mentor’s advice right away.  However sometime it takes time to sink in.  I received some advice related to answering questions about a year out of college.  About two years later, I told the person giving the advice that it finally clicked and now I understand what he was talking about!  At the time I did appreciate that the advice was given, but I wasn’t at the point yet where it could be useful.
  • empower and move forward with confidence – The mentee really is responsible for themselves and the mentor is just trying to help that person succeed.
  • discuss needs and circumstances openly and in confidence – One needs to know what’s going on to provide useful help and advice.  Yet often when we need advice, it’s because something problematic is going on or our innermost desires conflict with others.  Not the easiest thing to talk about in general.  Especially for technical people like us who are more comfortable with computers and logic.  Being assured of confidence allows one to “just talk” as if one is talking to a friend.  Sometimes that means your mentor (or one of your mentors) should be someone you know well or someone you don’t work with directly.
  • informal environment – Some environments are more informal than others.  Part of managing someone involves mentoring and providing career guidance.  This type of mentoring is extremely valuable because a manager knows more about a person’s job than anyone else.  It’s also valuable to have someone to talk to who is NOT your direct manager.  For one thing, it’s uncomfortable discussing things directly relating to your manager with your manager.  For another, no matter how much you trust your manager, there’s still a nagging feeling that the person is your manager which affects openness.  It’s hard to present an idea you haven’t thought through directly to your manager.  It’s also useful discussing things with someone else to gather more points of view.  This “other person” to talk to doesn’t need to be formally named a mentor.
  • in a position to be of positive help – There are multiple levels of help.  Sometimes a person just needs someone talk to.  Expressing ideas to someone else helps clear ones head and make connections between ideas.  This is the really basic level of help.  At higher levels of help, it advances it to making suggestions and asking questions to help the person think about solutions and next steps.

Formal mentoring tends to be easier to visualize.  As an example of informal mentoring, I talked to a collegue at JavaRanch (where I volunteer, not my “real” job) about something this weekend.  This is someone who I really respect – especially when it comes to process and team dynamics.  And with mentoring!  He asked me a bunch of questions to understand both the scenario and what I was thinking/what I wanted.  He also asked some higher level questions.  This was the most valueable thing for me.  If I had talked to someone I work with, this question would have been unlikely to come up because everyone would be thinking within the job and taking certain things for granted.  Now this is the only time I asked this particular person for advice (that I can recall.)  But I’ve absorbed so much from him over the years.  I think this shows that there is informal mentoring (“can I talk to you about this one thing” vs just learning from watching/listening to someone who doesn’t even realize they are mentoring.)

This Coupon Requires a Time Machine

Hope everyone is enjoying the black-Friday/cyber-Monday sales. Personally, I haven’t seen many good ones this year but I did come across this gem in my inbox. It offers an impressive 20% off all their products if you happen to own a time machine:


Hope everyone had a nice Thanksgiving!
-Scott