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.