MySQLで件数取得する場合は,select count(*)じゃなくてselect (index_key)の方が早い

けんすう」って打ったら件数でなくケンスウが出てくる僕はどうみてもKOF厨です本当にry
select count(*)する時にselect count(index_key)した方が早くなると聴いてやってみた.


・before

select
  dt.document_id,
  dt.term_id,
  -- TF
  (
    -- 文書Djにおける単語Wiの出現回数
    (
      select sum(frequency)
      from document_terms dt1
      where dt1.document_id = dt.document_id and dt1.term_id = dt.term_id
    )
    /
    -- 文書Djに出現する単語の総数(種類数ならcount(*)にする)
    (
      select sum(frequency)
      from document_terms dt2
      where dt2.document_id = dt.document_id
    )
  )
  *
  -- IDF
  log(
    -- 文書の数
    (
      select count(distinct document_id)
      from document_terms dt1
    )
    /
    -- 単語Wiを含む文書の数
    (
      select count(distinct document_id)
      from document_terms dt4
      where dt4.term_id = dt.term_id
    )
  ) as tf_idf
  from document_terms dt
  where dt.document_id = 1;


・after

select
  dt.document_id,
  dt.term_id,
  -- TF
  (
    -- 文書Djにおける単語Wiの出現回数
    (
      select sum(frequency)
      from document_terms dt1
      where dt1.document_id = dt.document_id and dt1.term_id = dt.term_id
    )
    /
    -- 文書Djに出現する単語の総数(種類数ならcount(*)にする)
    (
      select sum(frequency)
      from document_terms dt2
      where dt2.document_id = dt.document_id
    )
  )
  *
  -- IDF
  log(
    -- 文書の数
    (
      select count(id)
      from documents dt3
    )
    /
    -- 単語Wiを含む文書の数
    (
      select count(d.id)
      from documents d join document_terms dt4 on d.id = dt4.document_id
      where dt4.term_id = dt.term_id
    )
  ) as tf_idf
  from document_terms dt
  where dt.document_id = 1;


・結果

before 178 rows in set (18.26 sec)
after 178 rows in set (13.97 sec)


おお,確かに若干早くなってる(join使ってるのに).
データ数は1000件程度でやってみたから,件数増えたらもっと効果的なんだろうなぁ.


ちなみに,こんな風にしても同じくらいの速度だった.

select
  dt.document_id,
  dt.term_id,
  -- TF
  (
    -- 文書Djにおける単語Wiの出現回数
    (
      select sum(frequency)
      from document_terms dt1
      where dt1.document_id = dt.document_id and dt1.term_id = dt.term_id
    )
    /
    -- 文書Djに出現する単語の総数(種類数ならcount(*)にする)
    (
      select sum(frequency)
      from document_terms dt2
      where dt2.document_id = dt.document_id
    )
  )
  *
  -- IDF
  log(
    -- 文書の数
    (
      select count(id)
      from documents dt3
    )
    /
    -- 単語Wiを含む文書の数
    (
      select count(d.id)
      from documents d
      where d.id in (select document_id from document_terms dt4 where dt4.term_id = dt.term_id)
    )
  ) as tf_idf
  from document_terms dt
  where dt.document_id = 1;