読者です 読者をやめる 読者になる 読者になる

カイワレの大冒険 Third

技術的なことや他愛もないことをたまに書いてます

InnoDBのINFORMATION_SCHEMA TABLES Tableと実データのレコード数比率を出してみた

キャラメルコーンは一人で食うにはやはり一袋でかいなと痛感している@masudaKです。

information_schema.TABLESのデータどれくらい使えるだろうなと思い、簡単にデータ取ってみたので、その感想をば。
使ったMySQLのバージョンは5.5.24でございます。

MySQL 5.5 Reference Manual :: 20.21 The INFORMATION_SCHEMA TABLES Table」には以下のように書かれていまして、

For InnoDB tables, the row count is only a rough estimate used in SQL
optimization. (This is also true if the InnoDB table is partitioned.)

要はInnoDBを使ってると行数のカウントはラフだよ、ざっくり出してるからねと書かれております。

SELECT table_name, table_rows FROM information_schema.TABLES WHERE table_schema = 'DB_NAME';

とやればそれっぽいデータ取れるんですが、実データとどれくらい違うんだろうと思い、ちょっと取ってみました。
更新も一切走ってなく、ディスクにフラッシュした状態で、↑で取得したデータと以下のスクリプトを元に取得したデータでざっくりと比較してみました。

#!/bin/bash -e
USER='USER'
PASS='PASS'
DB='DB_NAME'
LOG_FILE="./mysql_table_count.log"


for TABLE in `mysql -u${USER} -p{PASS} -e "USE ${DB}; SHOW TABLES\G" | gawk '{ if (NR % 2 == 0) printf $2"\n"}'`
do
  echo "-----------   Getting ${TABLE} Information   -----------------------------" | tee -a "${LOG_FILE}"
  mysql -u${USER} -p${PASS} -e "SELECT count(*) FROM ${DB}.${TABLE};"  | tee -a "${LOG_FILE}"

  ELEVEL=$?
  if [ ${ELEVEL} -ne 0 ]; then
    echo "Failed: could not get information for ${TABLE}"  | tee -a "${LOG_FILE}"
  else
    echo "Success: ${TABLE}" | tee -a "${LOG_FILE}"
  fi
  echo '----------------------------------------' | tee -a "${LOG_FILE}"
done

結果は以下の様な感じ(かなり抜粋ですが…)。

以下の言う比率とは、information_schema.TABLESのtable_rowsカラムから得られた値を、COUNT(*)で取得した値で割った値です。なので、等しい場合は1となり、table_rowsの値が小さければ1より小さく、大きければ1より大きくなります。

|table_name  |比率 |
|table1       |1.000|
|table2       |1.186|
|table3       |0.961|
|table4       |1.052|
|table5       |1.060|
|table6       |2.045|
|table7       |1.023|
|table8       |1.196|
|table9       |0.909|
|table10      |1.021|
|table11      |1.273|
|table12      |1.000|
|table13      |0.929|
|table14      |1.040|
|table15      |0.939|
|table16      |1.000|
|table17      |0.996|
|table18      |1.000|
|table19      |1.015|
|table20      |1.051|
|table21      |1.000|
|table22      |1.000|
|table23      |0.854|

これでも一部ですが、やっぱ概算値だなぁと。2.045とかだとここまでずれるのかーと思ったり。

当然ではありますが、1.000、またはそれに近いのはレコード数がめちゃ小さいのが目立ちます。二桁とかそういうの。億でもそういうのは稀にあるので、そこら辺は難しいところですが、基本的にはレコード数は少なめですね。

大きくズレるの見るとレコード数少な目のものも大き目のものもありますが、よく更新されてるテーブルのような印象を受けます。更新処理が走るので、概算値がずれやすいのかなと。


いずれにせよ、深くは追えてないですが、上記のような印象を受けました。
InnoDBであまりcount(*)大量に走らせたくないのですが、たまにはということで。

あと、やっぱ5.5系は早いかもなーという気持ちも若干した次第です。