Introducing MySQL Visual Explain

Download MySQL Visual Explain

If you’ve ever wished you could see MySQL’s EXPLAIN output formatted as a tree, now you can. MySQL Visual Explain transforms EXPLAIN output into a hierarchical view of the query plan, which is significantly easier to read and understand.

What it does

MySQL Visual Explain is a command-line tool, not a Graphical User Interface (GUI). You can use it two ways:

  • Give it a query and some connection options, and it will connect and EXPLAIN the query, then show you the result as a tree.
  • Give it the output of EXPLAIN in any of several formats, and it will parse it and turn it into a tree.

Here’s a simple example. Given the following query,

select actor_id,
   (select count(film_id) from sakila.film join sakila.film_actor using(film_id))
from sakila.actor;

You get this EXPLAIN output:

+----+-------------+------------+-------+----------------+--------------------+---------+---------------------+------+-------------+
| id | select_type | table      | type  | possible_keys  | key                | key_len | ref                 | rows | Extra       |
+----+-------------+------------+-------+----------------+--------------------+---------+---------------------+------+-------------+
|  1 | PRIMARY     | actor      | index | NULL           | PRIMARY            | 2       | NULL                |  200 | Using index | 
|  2 | SUBQUERY    | film       | index | PRIMARY        | idx_fk_language_id | 1       | NULL                |  951 | Using index | 
|  2 | SUBQUERY    | film_actor | ref   | idx_fk_film_id | idx_fk_film_id     | 2       | sakila.film.film_id |    2 | Using index | 
+----+-------------+------------+-------+----------------+--------------------+---------+---------------------+------+-------------+

MySQL Visual Explain turns this into the following query execution plan:

SUBQUERY
+- JOIN
|  +- Index lookup
|  |  key            film_actor->idx_fk_film_id
|  |  possible_keys  idx_fk_film_id
|  |  key_len        2
|  |  ref            sakila.film.film_id
|  |  rows           2
|  +- Index scan
|     key            film->idx_fk_language_id
|     possible_keys  PRIMARY
|     key_len        1
|     rows           951
+- Index scan
   key            actor->PRIMARY
   key_len        2
   rows           200

You should read this as a depth-first tree traversal. In other words, the root of the tree is the output node — the last thing that happens in query execution.

As I said, this is a simple example. When your queries have many subqueries and/or UNIONs, you quickly get much more complicated EXPLAIN output, which is very hard to understand. It’s much easier to read the tree representation for complex queries. Here are thumbnails of the query execution plans of some real queries from a project I’ve worked on:

MySQL Visual Explain output on a complex queryMySQL Visual Explain output on a complex query

The corresponding EXPLAIN output is very hard to understand, even though I’ve become an expert on EXPLAIN. I can understand the tree view without trouble. I don’t think it matters how much of an expert I am, a tree view is always going to be easier to understand.

How it works

MySQL Visual Explain tries to reverse-engineer EXPLAIN by re-ordering and dividing the input into parent/child relationships. How exactly it happens is complex, though it can be expressed in code fairly succinctly. I wanted to write this tool nearly a year ago, but after studying EXPLAIN for a while, I found I just didn’t understand it well enough. Then this spring at the MySQL Conference and Expo 2007, I saw a talk on the Query Optimizer by Timour Katchaounov, who works on the optimizer team. Timour helped me grasp how MySQL executes queries. Most importantly, he showed a diagram of the execution plan as a left-deep tree. I always assumed the query execution plan was a bushy tree, but once I saw the left-deep tree I understood more about how MySQL works (for example, I now understand why MySQL doesn’t support FULL OUTER JOIN).

The crucial bridge between that and understanding EXPLAIN was a slide that showed the nodes of the tree mapped to rows in EXPLAIN. This made me see how to approach the problem. After spending hours reading the MySQL manual and source code, and studying many examples, I slowly understood how to go backwards from EXPLAIN to a tree.

It is not as simple as it sounds! There are many details, such as how to decide which nodes should be children of which other nodes (when there are no subqueries or UNIONs, of course it’s trivial). EXPLAIN’s output can be quite complex, and a moderately complicated query takes me a few minutes to reverse-engineer by hand — and most of the time I get it wrong. Maybe I can write the details in another blog post, or contribute them to MySQL’s documentation or the MySQL Forge wiki.

Download it

You can get the goodies from the Sourceforge MySQL Toolkit project page and read the documentation online at the MySQL Toolkit homepage.

If you find bugs

I couldn’t have written this tool without unit tests, especially since I had to start over twice when I found I was misunderstanding something major (that’s a huge plug for test-driven development). If you find a query it transforms wrong, please report it via the project’s Sourceforge bug tracking system. Please give the query and EXPLAIN output, so I can add it to the test suite.

Future plans

MySQL themselves, and many community members, have sometimes discussed the need for a tree view of EXPLAIN. I sincerely hope they implement that feature and make this little tool obsolete in future versions of MySQL. I also understand MySQL is trying to add more information to EXPLAIN. Currently it’s not possible to get a complete query execution plan from EXPLAIN, because it doesn’t show you everything the server does while executing the query. If MySQL adds information, I’ll update this tool. I have a feature request pending to show when a GROUP BY happens, for example.

I also specifically wrote this tool to be useful as a module, not just a command-line utility. This makes it possible for you to use the module in your own programs. I have a few ideas for this myself, though I may not get time to implement them.

Your support appreciated

Though the end result makes it look easy, this was a seriously hard project that took many evenings and weekends of research, testing, and coding, with many false starts. If you feel inclined, there’s a “support” link in the navigation bar at the top of this page! (For those of you who tried to send me something and it got returned, I’ve fixed that issue).

Technorati Tags:, , , , ,

You might also like:

  1. How to avoid an extra index scan in MySQL
  2. How to sync tables in master-master MySQL replication
  3. MySQL Query Profiler
  4. Progress on Maatkit bounty, part 3
  5. A case study in profiling queries in MySQL

11 Responses to “Introducing MySQL Visual Explain”


  1. 1 evan

    Great work! EXPLAIN can definitely be mysterious.

  2. 2 Ruturaj K. Vartak

    Its great to see such a tool come up, For long MySQL lacked something similar to a “Execution Plan” view as in MS-SQL server, I’d like to see a similar tool/could be u’r code into main MySQL client.

  3. 3 Peter Zaitsev

    Great Baron,

    (I know you sent me initial version to review and I did not reply to that email yet, sorry)

    This is a great tool especially for complex queries - EXPLAIN itself works good for Joins but once you get into a lot of subqueries it becomes nasty.

    You may also look at explain options to get more info such as partitions used etc.

  4. 4 Xaprb

    Thanks Peter.

    Partitions and other options are included, but not output by default if they are NULL. The textual tree-view output actually doesn’t show all the information in the tree built from EXPLAIN; I wanted to keep it as brief as possible. But if your EXPLAIN output includes partitions, you should see the results in the tree.

    This makes me realize, there’s no way with the –connect option to ask MySQL Visual Explain to EXPLAIN the command as EXPLAIN PARTITIONS! I will add an option to do that. This of course only affects what data it gets from the server, not how the tree is built; if you give it text as input instead of a command, it’ll show all the information it’s given.

    [EDIT] I see I’m too smart for myself. It runs EXPLAIN /*!50115 PARTITIONS*/ SELECT so it should work fine. I completely forgot that I did that.

  5. 5 Roland Bouman

    Baron! This is great, awesome!

  6. 6 Dave Shrewsbury

    Baron,

    This is really cool! FYI, I found a small bug and submitted a bug report per your instructions. The –socket option isn’t working.

    -Dave

  7. 7 Xaprb

    Thanks Dave! That probably means it is broken in many other tools too. I’ll take a look.

  1. 1 Tims Blog » Blog Archive » No More San Diego
  2. 2 All in a days work…
  3. 3 Log Buffer #56: a Carnival of the Vanities for DBAs « H.Tonguç YILMAZ Oracle Blog
  4. 4 MySQL visual explain « Eclesiastes

Leave a Reply

Please do not use this blog to get help with problems or bugs in Maatkit or innotop: use the Sourceforge forums, mailing list, or bug trackers. If you're asking for help with MySQL, please use the MySQL mailing list instead. I'm writing a book and my time is extremely limited :-)