Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mysql datetime field with index get a range 'like' vs. 'between and' performance

I just find mysql can query datetime using like:

like '2013-06-12%'

I think it can not use the index. I Google it, but can not find such subject directly. So I have a test using a table with 3308614 records. The first SQL:

SELECT * FROM subscription t WHERE DATE(t.active_time) = '2013-06-30';

All we know this SQL can not use the index and it takes 4 seconds to get the result. The second SQL:

SELECT * FROM subscription t WHERE t.active_time LIKE '2013-06-30%';

I don't know if it can use the index, but it takes 4 seconds too. The third SQL:

SELECT * FROM subscription t WHERE t.active_time > '2007-11-30' AND t.active_time < '2007-12-01';

All we know the third SQL can use the index, and it takes 0.016 second.

So I think 'like' can not use the index when query the datetime field, because mysql should convert datetime field to string first and send the string to like command. Is this correct ?

like image 925
bluearrow Avatar asked Jun 14 '13 05:06

bluearrow


People also ask

Can we create index on datetime column in MySQL?

This makes your datetime column an excellent candidate for an index if you are going to be using it in conditions frequently in queries. If your only condition is BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 30 DAY) and you have no other index in the condition, MySQL will have to do a full table scan on every query.

How do I select a date range in MySQL?

If you need to select rows from a MySQL database' table in a date range, you need to use a command like this: SELECT * FROM table WHERE date_column >= '2014-01-01' AND date_column <= '2015-01-01'; Of course you need to change: table.

How do I query between two dates using MySQL?

select *from yourTableName where yourColumnName between 'yourStartingDate' and curdate().

Is MySQL between inclusive for dates?

The MySQL BETWEEN Operator The values can be numbers, text, or dates. The BETWEEN operator is inclusive: begin and end values are included.


2 Answers

Assuming that t.active_time's type is DATETIME,

The following query cannot use an index because of the function call. All active_time must be converted on-the-fly to a DATE value before comparison with '2013-06-30'. This string is converted to a DATE value in the very first place, and this happens only once at the very beginning of the query.

SELECT * FROM subscription t WHERE DATE(t.active_time) = '2013-06-30';

The second query cannot use an index either for similar reasons. You are actually making a string comparison (because of the LIKE operator). All active_time values are converted to a string on-the-fly.

SELECT * FROM subscription t WHERE t.active_time LIKE '2013-06-30%';

Only the last one can use an index. The strings '2007-11-30' and '2007-12-01' are cast to DATETIME in this case, because the < and > operators allow this.

SELECT * FROM subscription t WHERE t.active_time > '2007-11-30' AND t.active_time < '2007-12-01';

The latter also applies to the = and BETWEEN operators.

For information, all types can be compared to a string with the LIKE operator, suffering from the same problem as described above, because of the implicit conversion it requires.

t.active_time = '2013-06-30' does not work as expected because '2013-06-30' is cast to a DATETIME value, that is to say '2013-06-30 00:00:00'.

like image 85
RandomSeed Avatar answered Nov 15 '22 16:11

RandomSeed


One alternative for such cases is to do something like this:

SELECT *
FROM subscription t
WHERE t.active_time BETWEEN '2013-06-30 00:00:00' AND '2013-06-30 23:59:59';

In the end you get all events from that day.

like image 43
RenatoSz Avatar answered Nov 15 '22 14:11

RenatoSz