web-dev-qa-db-ja.com

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

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

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

14
Benubird

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

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

_select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';_

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

16
Kevin Bott

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

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

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

3
Rick James