简体   繁体   中英

MySQL query take so long time in where clause

I have table structure like bellow:

id item_id created
1  5       2012-09-05 09:37:59
2  5       2012-09-05 10:25:09
3  5       2012-09-05 11:05:09
4  1       2012-09-05 10:25:09
5  3       2012-09-05 03:05:01

I want to know which item_id is most view by pass current date with WHERE clause as bellow:

SELECT item_id, COUNT( id ) AS TOTAL
FROM stats_item
WHERE DAY( created ) =  '05'
AND MONTH( created ) =  '07'
AND YEAR( created ) =  '2013'
GROUP BY item_id
ORDER BY TOTAL DESC 
LIMIT 0 , 30

The result query in MySql

Showing rows 0 - 29 ( 30 total, Query took 4.1747 sec)

It's take time up to 4.1747 sec

Bellow is index in table

Table        Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
stats_item   0          PRIMARY  1            id          A         2575580     NULL     NULL         BTREE
stats_item   1          created  1            created     A          515116     NULL     NULL   YES   BTREE

Why is query take so long time with WHERE clause and filter with YEAR, MONTH and DAY?

================================== Edit with EXPLAIN:

Field   Type                Null Key    Default Extra
id      int(11) unsigned    NO   PRI    NULL    auto_increment
item_id int(11) unsigned    YES         NULL    
created timestamp           YES  MUL    NULL    

Try to add composite index: created+item_id
Try to use query like:

SELECT item_id, COUNT( id ) AS TOTAL FROM stats_item
WHERE created >= "2013-07-05" and created <= "2013-07-05 23:59:59" 
GROUP BY item_id ORDER BY TOTAL DESC LIMIT 0 , 30

Try this. I bet it runs faster. When you use functions on dates, the engine will generally ignore the indices. Comparing a range directly to the date field should be faster.

SELECT   item_id, COUNT( id ) AS TOTAL
FROM     stats_item
WHERE    created BETWEEN '2013-05-07' AND '2013-05-07 23:59:59'
GROUP BY item_id
ORDER BY TOTAL DESC 
LIMIT 0, 30

What does it take a long time? Two possible reasons. One is that the table is doing a full-table scan (because the functions in the where clause preclude the use of indexes). The other is because there are lots and lots of rows.

The first problem is solved by JW's solution:

WHERE   created >= '2013-07-05' AND
        created < '2013-07-05' + INTERVAL 1 DAY

Direct comparisons, with no functions, should always use an index.

Because this is not the problem, let me assume that there are lots and lots of rows for the day. If so, the problem is something called thrashing that can happen with indexes. This basically means that every matching reference is on a different page, so you still have to read in lots of pages. The fix to this is to add the item_id to the index. In the create table statement, you would do:

index (created, item_id)

Or you would do:

create index stats_item_created_item_id on stats_item(created, item_id)

In table stats_item it's really have a lot of row. I try to add INDEX with created, item_id the result is still slow.

The only way i use is between. It's really better that it's took only 0.0686 sec very difference from 4.1747 sec

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM