web-dev-qa-db-ja.com

MySQL:行数をカウントする最速の方法

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()

これは明らかにデータベースの領域であり、内部的にこのようなことを判断する場合、データベースエンジンは他の誰よりも高速である必要があるため、最初の方法はより高速であると考えられます。

106
Franz

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ステートメントの内容に帰着します。多数の行(数万、数百万以上)がある場合、インデックスの使用方法に注意を払う必要があります。

117

チームメイトと話した後、リカードは私たちに、より速い方法は次のようであると言った。

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 で完全な議論を見つけることができます

45
MagMax

素晴らしい質問、素晴らしい答え。誰かがこのページを読んでいて、その部分を見逃している場合、結果をエコーする簡単な方法は次のとおりです。

$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$count = $num["id"];
echo("$count");
31
Dan Horvat

私は、以下が最も速い応答時間を与えることを常に理解していました。

SELECT COUNT(1) FROM ... WHERE ...
13
adarshr

このクエリ(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 |

13
lepe

結果セット全体のカウントを取得する必要がある場合は、次のアプローチを使用できます。

SELECT SQL_CALC_FOUND_ROWS * FROM table_name LIMIT 5;
SELECT FOUND_ROWS();

これは通常、COUNTを使用するよりも高速ではありませんが、内部で計算を実行し、ユーザーにデータを返送しないため、パフォーマンスの改善が疑われるため、逆の場合が考えられます。

これらの2つのクエリを実行することは、合計を取得するためのページ分割には適していますが、WHERE句を使用する場合には特に適していません。

6
Alex Rashkov

いくつかのベンチマークを行ってCOUNT(*)COUNT(id)の実行時間を比較しました(idはテーブルの主キー-インデックス付き)。

試行回数:10 * 1000クエリ

結果:COUNT(*)は7%高速です

グラフの表示: ベンチマークグラフ

私のアドバイスは、使用することです:SELECT COUNT(*) FROM table

5
SamC

おそらく、SELECT max(Id) - min(Id) + 1の実行を検討することをお勧めします。これは、IDがシーケンシャルで行が削除されない場合にのみ機能します。ただし、非常に高速です。

1
sky-dev

これを試して:

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

私はドイツ政府のテーブルを時々6000万件のレコードで処理しました。

また、合計行数を何度も知る必要がありました。

そのため、データベースプログラマーは、すべてのテーブルのレコードが常に1つであり、合計レコード番号が格納されているレコードであると判断しました。 INSERT行またはDELETE行に応じて、この数値を更新しました。

他のすべての方法を試しました。これは断然最速の方法です。

1
Scoobeedo Cool

主キーのwhere条件を指定したcount(*)ステートメントは、フルテーブルスキャンを回避するために行カウントをはるかに速く返しました。

SELECT COUNT(*) FROM ... WHERE <PRIMARY_KEY> IS NOT NULL;

これは私にとってよりもはるかに速かった

SELECT COUNT(*) FROM ...
0
ayakout

EXPLAIN SELECT id FROM ....は私のためにトリックをしました。そして、結果のrows列の下の行数を見ることができました。

0
ssrp