0

I have a query that looks like the following:

SELECT * from foo
  WHERE days >= DATEDIFF(CURDATE(), last_day)

In this case, days is an INT. last_day is a DATE column.

so I need two individual indexes here for days and last_day?

O. Jones
  • 103,626
  • 17
  • 118
  • 172
randombits
  • 47,058
  • 76
  • 251
  • 433
  • Since you are using a function, last_day can't be used as an index. Days could but the performance gain really depend on the variance of the data. – Guillaume F. Jul 06 '16 at 22:20

3 Answers3

5

This query predicate, days >= DATEDIFF(CURDATE(), last_day), is inherently not sargeable.

If you keep the present table design you'll probably benefit from a compound index on (last_day, days). Nevertheless, satisfying the query will require a full scan of that index.

Single-column indexes on either one of those columns, or both, will be useless or worse for improving this query's performance.

If you must have this query perform very well, you need to reorganize your table a bit. Let's figure that out. It looks like you are trying to exclude "overdue" records: you want expiration_date < CURDATE(). That is a sargeable search predicate.

So if you added a new column expiration_date to your table, and then set it as follows:

 UPDATE foo SET expiration_date = last_day + INTERVAL days DAY

and then indexed it, you'd have a well-performing query.

Community
  • 1
  • 1
O. Jones
  • 103,626
  • 17
  • 118
  • 172
0

You must be careful with indexes, they can help you reading, but they can reduce performance in insert.

You may consider to create a partition over last_day field.

I should try to create only in last_day field, but, I think the best is making some performance tests with different configurations.

duardito
  • 107
  • 2
  • 8
0

Since you are using an expression in the where criteria, mysql will not be able to use indexes on any of the two fields. If you use this expression regularly and you have at least mysql v5.7.8, then you can create a generated column and create an index on it.

The other option is to create a regular column and set its value to the result of this expression and index this column. You will need triggers to keep it updated.

Shadow
  • 33,525
  • 10
  • 51
  • 64