Copy & Paste Engineer

【Mysql】テーブルの件数を取得する際に TABLE_ROWS と COUNT の違いの注意点

【Mysql】テーブルの件数を取得する際に TABLE_ROWS と COUNT の違いの注意点

テーブルのデータ量が多く、COUNT だと時間が掛かるため、INFORMATION_SCHEMATABLES.TABLE_ROWS から件数を確認してみたのですが、これが実際の件数と違うので注意が必要です。

現象

information_schema.table_rows の値と count した件数が違う。

information_schema.table_rows から行数を取得。

SELECT
  table_name,
  table_rows
FROM
  information_schema.tables
WHERE
  table_schema = 'db_name'
  AND table_name = 'tbl_name';
table_name table_rows
tbl_name 12345

select count(*) から行数を取得。

SELECT COUNT(*) FROM tbl_name;
table_name COUNT(*)
tbl_name 12999

上記のように table_rowscount で違いが生じます。

原因

table_rowscount の差異の原因は以下のためです。

TABLE_ROWS 行数。 MyISAM などの一部のストレージエンジンは、正確な数を格納します。 InnoDB などのほかのストレージエンジンの場合、この値は概算であり、実際の値と 40% から 50% まで異なる可能性があります。 このような場合、正確な数を取得するには SELECT COUNT(*) を使用します。 MySQL :: MySQL 8.0 リファレンスマニュアル :: 26.38 INFORMATION_SCHEMA TABLES テーブル

対処

対処方法としては最適化です。 以下いずれかの対処で table_rows が正確なものになることを確認しました。

INDEXの最適化

読み取りロックが発生します。

ANALYZE TABLE tbl_name;

テーブルの最適化

どちらかを実行するだけでテーブルの最適化が行われます。 テーブルロックが発生するので注意してください。

OPTIMIZE TABLE tbl_name;
ALTER TABLE tbl_name ENGINE INNODB;

自動的に最適化されるタイミング

漢(オトコ)のコンピュータ道: 大人のためのInnoDBテーブルとの正しい付き合い方。

  • 前回インデックス統計情報を更新してから、テーブルの行数全体の1/16が更新された。
  • 前回インデックス統計情報を更新してから、20億行以上更新された。

auto_increment を利用する方法

別の手として該当のテーブルに auto_increment が設定されている場合且つ物理削除を行われていないのであれば、auto_increment を取得すれば現在の行数として扱えるかと思います。

SELECT
  table_name,
  auto_increment-1
FROM
  information_schema.tables
WHERE
  table_schema = 'db_name'
  AND table_name = 'tbl_name';

auto_increment1 から始まるので -1 する。

table_name auto_increment-1
tbl_name 13210

参考