MySQL-行のカウントにcount(*)とinformation_schema.tablesを使用することの違い


15

数百万行のテーブル内の行数をすばやくカウントする方法が必要です。Stack Overflowで「MySQL:行数をカウントする最も速い方法」という投稿を見つけました。これは私の問題を解決するように見えました。バユアはこの答えを提供しました:

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

スキャンの代わりにルックアップのように見えるので私は好きでしたので、高速でなければなりませんが、テストすることにしました

SELECT COUNT(*) FROM table 

パフォーマンスの違いがどれほどあったかを確認します。

残念ながら、以下に示すように異なる回答が得られます。

ここに画像の説明を入力してください

質問

回答が約200万行異なるのはなぜですか?全表スキャンを実行するクエリの方が正確な数値であると推測していますが、この遅いクエリを実行せずに正しい数値を取得する方法はありますか?


実行ANALYZE TABLE data_302しましたが、0.05秒で完了しました。クエリを再度実行すると、34384599行という非常に近い結果が得られますが、それでもselect count(*)34906061行と同じ数ではありません。分析テーブルはすぐに戻り、バックグラウンドで処理されますか?これはテストデータベースであり、現在は作成されていないことに言及する価値があると思います。

テーブルがどれだけ大きいかを誰かに伝えるだけの場合は誰も気にしませんが、その数字を使用してデータベースを照会する「同じサイズの」非同期クエリを作成するコードに行カウントを渡したいと思いました。並行して、「Alexander Rubinによるパラレルクエリの実行によるクエリパフォーマンスの低下」で示した方法に似ています。現状では、最高のIDを取得するだけでSELECT id from table_name order by id DESC limit 1、テーブルが断片化しすぎないように願っています。

回答:


23

テーブルの行を「カウント」する方法はさまざまです。最適なものは要件(カウントの精度、実行頻度、テーブル全体のカウントが必要か、変数wheregroup by句を使用するかなど)によって異なります。

  • a)通常の方法。それらを数えるだけです。

    select count(*) as table_rows from table_name ; 

    精度:クエリ実行時の100%正確なカウント。
    効率性:大きなテーブルには向いていません。(MyISAMテーブルのための速い見事ですが、誰もそれがInnoDBのオーバー非常に多くの欠点を持っているとして、これらの日のMyISAMを使用していない。「見事速い」全体のMyISAMテーブルの行をカウントするときだけ適用されます-クエリがある場合WHEREの条件を、それをまだテーブルまたはインデックスをスキャンする必要があります。)
    エンジンは、正確なカウントを取得するためにいずれかを実行し、テーブル全体またはインデックス全体をスキャンする必要があるため、それは、テーブルのサイズに依存InnoDBテーブルについて。テーブルが大きいほど、取得に時間がかかります。

  • b)SQL_CALC_FOUND_ROWSおよびを使用しFOUND_ROWS()ます。少数の行も必要な場合は、前の方法の代わりに使用できます(を変更しますLIMIT)。私はそれがページングに使用されるのを見ました(いくつかの行を取得すると同時に、何がint合計であるかを知り、pgegの数を計算します)。

    select sql_calc_found_rows * from table_name limit 0 ; 
    select found_rows() as table_rows ;

    精度:前と同じ。
    効率:前と同じ。

  • c)information_schemaテーブルをリンクされた質問として使用する:

    select  table_rows
    from    information_schema.tables
    where   table_schema = 'database_name'
      and   table_name = 'table_name' ;

    精度:近似値のみ。テーブルが頻繁な挿入および削除のターゲットである場合、結果は実際のカウントから大きく外れることがあります。これは、ANALYZE TABLEより頻繁に実行することで改善できます。
    効率性:非常に良い、それはすべてのテーブルには触れていません。

  • d)データベース(別の「カウンター」テーブル)にカウントを保存し、テーブルに挿入、削除、または切り捨てが行われるたびにその値を更新します(これは、トリガーまたは挿入および削除手順を変更することで実現できます) 。
    これにより、挿入と削除のたびに追加の負荷がかかりますが、正確なカウントが提供されます。

    精度:100%の正確なカウント。
    効率性:非常に良好です。別のテーブルから単一の行のみを読み取る必要があります。
    ただし、データベースに追加の負荷がかかります。

  • e)アプリケーション層にカウントを保存(キャッシュ)し、1番目の方法(または以前の方法の組み合わせ)を使用します。例:10分ごとに正確なカウントクエリを実行します。2つのカウント間の平均時間では、キャッシュされた値を使用します。

    精度:概算ですが、通常の状況ではそれほど悪くはありません(数千の行が追加または削除される場合を除く)。
    効率性:非常に良好で、値は常に利用可能です。


1

の代わりに、正確なテーブル行カウントデータINNODBが必要information_schema.INNODB_SYS_TABLESTATS.NUM_ROWSな場合information_schema.TABLES.TABLE_ROWS

詳細をここに投稿しました:https : //stackoverflow.com/questions/33383877/why-does-information-schema-tables-give-such-an-unstable-answer-for-number-of-ro/49184843#49184843


1
間違った情報... 「INNODBについてあなたは、正確なテーブルの行のためのinformation_schema.INNODB_SYS_TABLESTATS.NUM_ROWSをしたい:」 マニュアルははっきり言って、推定NUM_ROWScolum
レイモンドNijland
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.