かみぽわーる

kamipo's blog

MySQL(InnoDB)でCOUNTしたくないとき

たとえば、MySQL を使ったお手軽メッセージキュー実装 - ドワンゴ 研究開発ブログに出てくるようなInnoDBをメッセージキューのように使っているときに、キューにどれだけメッセージが溜まってるかを確認したいとき、普通に考えるとCOUNTすると思う。

SELECT COUNT(*) AS count FROM test_queue;

この軽い気持ちでしたCOUNTが、もしうっかりキューに100万レコードぐらいあったりするとInnoDBだとPRIMARYキー総なめとかしちゃってレスポンスにかかる0.1秒ぐらいのあいだ罪悪感に苛まれることでしょう。

このとき冷静に考えると、もしキューが1件も処理されていなければ、idはauto_incrementなので特に細工していなければ

SELECT MAX(id) AS count FROM test_queue;

これも全体のレコード数に等しいでしょう。

キューが既に何件か処理されている場合でも、idが小さいほうから順番に処理されていくので

SELECT MAX(id) - MIN(id) + 1 AS count FROM test_queue;

これでも全体のレコード数に等しくなるはずです。

EXPLAINを見ても

EXPLAIN SELECT MAX(id) - MIN(id) + 1 AS count FROM test_queue\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Select tables optimized away
1 row in set (0.01 sec)

Select tables optimized awayと出てるだけあってレコード数が増えても一瞬でレスポンスが返ってきます。


こういうユースケースは実際ないかもしれないけど、とりあえずメモ。