< Home

Explain support for last, pluck and count


avatar Petrik de Heus

In Rails, explain can be called on a relation to explain how the database would execute a query. For example, this allows you to see if the database is using an index (good) or maybe filesort (not so good):

User.all.explain
# => EXPLAIN SELECT `users`.* FROM `users`
# +----+-------------+-------+------------+...+-------------+
# | id | select_type | table | partitions |...| Extra       |
# +----+-------------+-------+------------+...+-------------+
# |  1 | SIMPLE      | users | NULL       |...| Using index |
# +----+-------------+-------+------------+...+-------------+
# 1 row in set (0.00 sec)

Currently explain doesn’t work for queries using last, pluck or count, as these return the actual result instead of a relation:

User.count
# => 15

User.count.explain
# => undefined method `explain' for an instance of Integer (NoMethodError)

For Rails 8 I’ve added support for some methods by letting explain return a proxy instead:

User.all.explain.count
# => "EXPLAIN SELECT COUNT(*) FROM `users`"
# +----+-------------+-------+------------+...+-------------+
# | id | select_type | table | partitions |...| Extra       |
# +----+-------------+-------+------------+...+-------------+
# |  1 | SIMPLE      | users | NULL       |...| Using index |
# +----+-------------+-------+------------+...+-------------+
# 1 row in set (0.00 sec)

The supported methods are pluck, first, and last, as well as the calculation methods: average, count, maximum, minimum, and sum.

This change breaks the existing behaviour in that it requires calling inspect after explain. However, as explain is mostly used from the commandline, this won’t be a problem as inspect is called automatically in IRB.