MySQLで行数をカウントする方法はどれが速いですか?
この:
SELECT COUNT(*) FROM ... WHERE ...
または、代替案:
SELECT 1 FROM ... WHERE ...
// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()
これは明らかにデータベースの領域であり、内部的にこのようなことを判断する場合、データベースエンジンは他の誰よりも高速である必要があるため、最初の方法はより高速であると考えられます。
COUNT(*)
を実行すると、count列のインデックスが取得されるため、最良の結果が得られます。 MyISAMエンジンを使用したMysqlは実際に行カウントを保存します。すべての行をカウントしようとするたびにすべての行をカウントするわけではありません。 (主キーの列に基づく)
PHPを使用して行をカウントすることは、mysqlからphpにデータを送信する必要があるため、あまりスマートではありません。 mysql側で同じことを達成できるのに、なぜそうするのですか?
COUNT(*)
が遅い場合は、クエリでEXPLAIN
を実行し、インデックスが実際に使用されているかどうか、およびどこにインデックスを追加するかを確認する必要があります。
以下はfastestの方法ではありませんが、COUNT(*)
が実際に適合しない場合があります-結果のグループ化を開始すると、問題、COUNT
は実際にはすべての行をカウントしません。
解決策はSQL_CALC_FOUND_ROWS
です。これは通常、行を選択するときに使用されますが、ページの合計行数を知る必要があります。データ行を選択するときは、SELECTの後にSQL_CALC_FOUND_ROWS
キーワードを追加するだけです。
SELECT SQL_CALC_FOUND_ROWS [needed fields or *] FROM table LIMIT 20 OFFSET 0;
必要な行を選択したら、次の1つのクエリでカウントを取得できます。
SELECT FOUND_ROWS();
FOUND_ROWS()
は、データ選択クエリの直後に呼び出す必要があります。
結論として、すべては実際には、エントリの数とWHEREステートメントの内容に帰着します。多数の行(数万、数百万以上)がある場合、インデックスの使用方法に注意を払う必要があります。
チームメイトと話した後、リカードは私たちに、より速い方法は次のようであると言った。
show table status like '<TABLE NAME>' \G
ただし、結果が正確でない場合があることを覚えておく必要があります。
コマンドラインからも使用できます:
$ mysqlshow --status <DATABASE> <TABLE NAME>
詳細: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html
そして、あなたは mysqlperformanceblog で完全な議論を見つけることができます
素晴らしい質問、素晴らしい答え。誰かがこのページを読んでいて、その部分を見逃している場合、結果をエコーする簡単な方法は次のとおりです。
$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$count = $num["id"];
echo("$count");
私は、以下が最も速い応答時間を与えることを常に理解していました。
SELECT COUNT(1) FROM ... WHERE ...
このクエリ(bayuahが投稿したものに似ています)は、データベース内のすべてのテーブルカウントのニースサマリーを示します(Ivan Cachicatariによる ストアドプロシージャの簡略版 を強くお勧めします)。
SELECT TABLE_NAME AS 'Table Name', TABLE_ROWS AS 'Rows' FROM information_schema.TABLES WHERE TABLES.TABLE_SCHEMA = '
YOURDBNAME' AND TABLES.TABLE_TYPE = 'BASE TABLE'
;
例:
+-----------------+---------+ | Table Name | Rows | +-----------------+---------+ | some_table | 10278 | | other_table | 995 |
結果セット全体のカウントを取得する必要がある場合は、次のアプローチを使用できます。
SELECT SQL_CALC_FOUND_ROWS * FROM table_name LIMIT 5;
SELECT FOUND_ROWS();
これは通常、COUNT
を使用するよりも高速ではありませんが、内部で計算を実行し、ユーザーにデータを返送しないため、パフォーマンスの改善が疑われるため、逆の場合が考えられます。
これらの2つのクエリを実行することは、合計を取得するためのページ分割には適していますが、WHERE
句を使用する場合には特に適していません。
いくつかのベンチマークを行って、COUNT(*)
とCOUNT(id)
の実行時間を比較しました(idはテーブルの主キー-インデックス付き)。
試行回数:10 * 1000クエリ
結果:COUNT(*)
は7%高速です
グラフの表示: ベンチマークグラフ
私のアドバイスは、使用することです:SELECT COUNT(*) FROM table
おそらく、SELECT max(Id) - min(Id) + 1
の実行を検討することをお勧めします。これは、IDがシーケンシャルで行が削除されない場合にのみ機能します。ただし、非常に高速です。
これを試して:
SELECT
table_rows "Rows Count"
FROM
information_schema.tables
WHERE
table_name="Table_Name"
AND
table_schema="Database_Name";
私はドイツ政府のテーブルを時々6000万件のレコードで処理しました。
また、合計行数を何度も知る必要がありました。
そのため、データベースプログラマーは、すべてのテーブルのレコードが常に1つであり、合計レコード番号が格納されているレコードであると判断しました。 INSERT行またはDELETE行に応じて、この数値を更新しました。
他のすべての方法を試しました。これは断然最速の方法です。
主キーのwhere条件を指定したcount(*)ステートメントは、フルテーブルスキャンを回避するために行カウントをはるかに速く返しました。
SELECT COUNT(*) FROM ... WHERE <PRIMARY_KEY> IS NOT NULL;
これは私にとってよりもはるかに速かった
SELECT COUNT(*) FROM ...
EXPLAIN SELECT id FROM ....
は私のためにトリックをしました。そして、結果のrows
列の下の行数を見ることができました。