即使在列

时间:2015-12-23 11:31:13

标签: mysql mysql-slow-query-log

我正在使用一个mysql服务器,其中我设置了慢速查询日志,其中包含以下设置

log-slow-queries=/var/log/mysql/mysql-slow-queries.log
long_query_time=1
log-queries-not-using-indexes

我在mysql事件中每分钟都设置了以下事件。

UPDATE  mytable SET playing = 0
    WHERE  playing != 0
      AND  ( TIMESTAMPDIFF( MINUTE , lastplayed, NOW( )) >10 )
       OR  ( lastplayed IS NULL
              AND  ispresent= 0
           );

现在所有这些列playing, lastplayed, and ispresent都被编入索引,但这仍然出现在慢速查询日志中,其中包含以下详细信息

# Query_time: 0.000585  Lock_time: 0.000159 Rows_sent: 0  Rows_examined: 316

为什么此查询在慢速日志中显示?

2 个答案:

答案 0 :(得分:0)

我的猜测是,当你在函数中使用lastplayed时(在这种情况下为TIMESTAMPDIFF),不能使用索引。 MySQL不够聪明,无法理解您正在寻找all lastplayed stamps which are older than 10 minutes。因此它遍及所有行。

相反,你可以使用它:

... AND lastplayed < DATE_SUB(NOW(), INTERVAL 10 MINUTE) ...

然后MySQL只计算DATE_SUB ONCE,然后可以将lastplayed与实际整数值进行比较。这样MySQL再次使用索引就足够聪明了。

详细原因:
想象一下,你编写自己的MySQL函数(伪代码):

function weirdFunction(Integer i): {
    if (RAND() < 0.5) return i;
    else return 0;
}

现在,当您想要运行查询时:

... AND weirdFunction(lastplayed) = 0 ...

MySQL如何知道哪些最后显示的值会给出哪个结果?它不可能。它需要为所有行执行功能才能找到答案。因此,不能使用索引。

答案 1 :(得分:0)

通过两个OR摆脱UPDATEsOR的每一面都有一个{<1}}:

UPDATE  mytable SET playing = 0
    WHERE  lastplayed < NOW() - INTERVAL 10 MINUTE;
UPDATE  mytable SET playing = 0
    WHERE  lastplayed IS NULL
      AND  ispresent= 0; 

假设你有优先权。)

那些需要并使用这个“复合”指数:

INDEX(lastplayed, ispresent)

(每列的单个索引效率不高。)