I have a large table in MySQL with a slow query partly due to a condition like WHERE sent_at IS NULL
. sent_at
is a nullable datetime column but here we only want to check if it’s null so a standard index across all values would be wasteful.
I’ve discovered that creating a functional index with ISNULL()
or IS NULL
works but it is never used for queries.
E.g.
ALTER TABLE users ADD INDEX index_users_sent_at_is_null ((ISNULL(sent_at)));
Followed by the query:
SELECT COUNT(*) FROM users WHERE (sent_at IS NULL);
Will have a (JSON) EXPLAIN
output with access_type: "ALL"
and no possible or selected keys listed.
Doing the equivalent for YEAR(sent_at)
works as expected by using the relevant functional index, so there is something special about IS NULL
even though the virtual hidden column the functional index produces correctly contains 0 or 1.
Is there an elegant way to make this work?