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.