Explainが答えを知っているのに、なぜcount(*)が遅いのですか?


14

このクエリ:select count(*) from planner_event実行に非常に長い時間がかかります-とても長いので、終了する前にそれをgaveめて殺しました。ただし、実行するexplain select count(*) from planner_eventと、出力に列数(14m)の列が表示されます。

Explainが行数を即座に取得できるのに、count(*)の実行に時間がかかるのはなぜですか?


WHERE原因のないCOUNT(*)は、InnoDBエンジンでテーブルスキャンを実行します。COUNTはテーブルのヘッダーファイルに保持されているため、MyISAMはカウントを直接配信できます。
レイモンドナイランド

回答:


16

Explainは、以前に収集された統計(クエリオプティマイザーが使用)を使用しています。実行すると、select count(*)すべてのデータ・ブロックを読み込みます。

推定行数を取得する安価な方法を次に示します。

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

行ったとしてもselect count(id)、セカンダリインデックスがオンになっていない限り、非常に長い時間がかかる場合がありますididプライマリキーも想定)。すべてのデータ(行データを含む)はBツリーインデックスに格納されるため、aの実行select count(PK_COLUMN)は依然としてかなりの量のIOです(すべてのデータページを読み取る必要があります)。PKフィールドにセカンダリインデックスがある場合、カウントを実行するために実行するIOが少なくなります。


I_S.TABLESは、あなたと同じ推定値EXPLAIN与えます。
リックジェームズ

AND TABLE_SCHEMA='my_database'別のデータベースに同じ名前のテーブルがある場合、クエリが欠落しています。そうでない場合、複数の結果が返されます。
cz

3

Explainは、オプティマイザーの事柄を推定するために使用されるいくつかの「統計」から数値を取得します。その数は正確とはほど遠い場合があります。正確な値よりも2倍(高いまたは低い)を超えることがあります。

COUNT(*)InnoDBテーブルでを実行すると、テーブルをスキャンして、他の接続によって挿入/削除されているがまだ「コミット」されていないビジーなレコードをカウントしないようにする必要があります。実際には、(テーブルを含むPRIMARY KEY)テーブル全体ではなく、何らかのインデックスでフルスキャンを実行するだけで十分です。

RAMはどれくらいありますか?の価値はinnodb_buffer_pool_size何ですか?RAMの約70%である場合に役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.