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

の両側に 1 つずつ、OR2 つの を実行して を取り除きます。UPDATEsOR

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

(それはあなたが優先権を持っていると仮定しています。)

これらは、この 1 つの「複合」インデックスを必要とし、使用します。

INDEX(lastplayed, ispresent)

(各列の個々のインデックスは効率的ではありません。)

于 2015-12-24T02:55:18.877 に答える
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 に答える