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?

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top