0

我正在使用一个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

为什么这个查询显示在慢日志中?

4

2 回答 2

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 应该如何知道哪个 lastplayed 值会给出哪个结果?它不能。它需要对所有行执行该功能才能找出答案。因此不能使用索引。

于 2015-12-23T11:35:58.437 回答
0

OR通过做两个来摆脱 ,UPDATEs每侧一个OR

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)

(每列上的单个索引不会那么有效。)

于 2015-12-24T02:55:18.877 回答