简体   繁体   English

MySQL查询在where子句中花费很长时间

[英]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: 我想知道通过WHERE子句的当前日期通过以下日期最多查看哪个item_id:

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 MySql中的结果查询

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

It's take time up to 4.1747 sec 最多需要4.1747秒的时间

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? 为什么查询使用WHERE子句需要这么长时间,而使用YEAR,MONTH和DAY进行过滤呢?

================================== Edit with EXPLAIN: =================================使用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 尝试添加复合索引: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). 一种是该表正在执行全表扫描(因为where子句中的功能排除了使用索引)。 The other is because there are lots and lots of rows. 另一个是因为有很多行。

The first problem is solved by JW's solution: JW的解决方案解决了第一个问题:

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. 解决此问题的方法是将item_id添加到索引中。 In the create table statement, you would do: create table语句中,您将执行以下操作:

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. 在表stats_item中,确实有很多行。 I try to add INDEX with created, item_id the result is still slow. 我尝试将INDEX与创建的item_id添加在一起,结果仍然很慢。

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 最好只花0.0686秒,与4.1747秒相差甚远

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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