Indexing a date column in MySQL doesn't work if a date function is used
-
04-03-2021 - |
Question
I have a table with the following schema
table_name
id int
task_id int
completed_date datetime (INDEX IX_TBL_NAME_COMPLETED_DATE)
I run EXPLAIN on this query
EXPLAIN
SELECT
*
FROM table_name TBL
WHERE
TBL.completed_date BETWEEN date1 AND date2
This query runs and fetches records using the index on completed_date
However, While running the same query with a date function
EXPLAIN
SELECT
*
FROM table_name TBL
WHERE
CONVERT_TZ(TBL.completed_date, timezone1, timezone2) BETWEEN date1 AND date2
The index isn't made use of resulting in a slow query.
Can someone explain the reason behind this behavior and solution to optimize queries like this?
Solution
This is a common issue with functional transformations of any type not only dates. To avoid this issue just move the transformation to the constant side of comparison. Instead of
WHERE CONVERT_TZ(TBL.completed_date, timezone1, timezone2)
BETWEEN date1
AND date2
use the next syntax: (notice the reverse transformation of the TZs)
WHERE TBL.completed_date
BETWEEN CONVERT_TZ( date1, timezone2 , timezone1 )
AND CONVERT_TZ( date2, timezone2 , timezone1 )
The reason of that behaviour is that plain index contains the plain values ordered by itself. Functional indexes implemented in mysql-8.0.13+
can store the values ordered by some function. And only that function can be indexed on lookups. Sometimes it's impossible to move the fuctional transformation to the constant side, so the functional index is the only option.