Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DATE() MONTH() etc. functions slow down query

I have a table Posts with a lot of records. I want to show user today posts, it is about 3-4 k.

creation_date - DATETIME field. This field has index.

In my query i simple filter records with query:

 SELECT posts.title AS post_title
 WHERE date(posts.creation_date) = DATE('2016-06-11')

This query performing 14 seconds.

Then i changed it to:

SELECT posts.title AS post_title 
WHERE pending_posts.creation_date > CONVERT('2016-06-11', DATETIME) 
AND pending_posts.creation_date < CONVERT('2016-06-11', DATETIME) + INTERVAL 1 DAY

And it takes 0.2 seconds...

Why this happens ? And how do i convert MONTH(posts.creation_date) or YEAR(posts.creation_date) because they slow down queries too, but i need show posts per month and per year.

like image 234
Arti Avatar asked Jun 12 '16 18:06

Arti


People also ask

Which function in SQL Server can we use to capture the month of a date?

To get a month from a date field in SQL Server, use the MONTH() function. This function takes only one argument – the date.

How do I get last 7 days record in SQL?

We use system function now() to get the latest datetime value, and INTERVAL clause to calculate a date 7 days in the past.

How to get date in SQL query?

SQL Server GETDATE() Function The GETDATE() function returns the current database system date and time, in a 'YYYY-MM-DD hh:mm:ss.mmm' format. Tip: Also look at the CURRENT_TIMESTAMP function.


1 Answers

it is a very bad idea to use functions on a field in the where clause. when you do this MySQL must read ALL rows (FULL TABLE SCAN) to see whats the result anfter the function and the its compare it with the constant.

Its much better to use function on the constant part the its convert only one time and the query can use a index.

for one DAY

SELECT ... WHERE datetimefield between '2016-01-05 00:00:00' AND '2016-01-05 23:59:59';

or

SELECT ... WHERE datetimefield between '2016-01-05 00:00:00' AND '2016-01-05 00:00:00' + INTERVAL 1 DAY

for one month

SELECT ... WHERE datetimefield between '2016-06-01 00:00:00' AND '2016-06-01 00:00:00' + INTERVAL 1 MONTH;

You can see the work of your query in the execution plan:

EXPLAIN SELECT posts.title AS post_title
 WHERE date(posts.creation_date) = DATE('2016-06-11');

and

EXPLAIN SELECT posts.title AS post_title 
WHERE pending_posts.creation_date > CONVERT('2016-06-11', DATETIME) 
AND pending_posts.creation_date < CONVERT('2016-06-11', DATETIME) + INTERVAL 1 DAY
like image 155
Bernd Buffen Avatar answered Sep 27 '22 21:09

Bernd Buffen