Tips.7 続)本当にCOUNT(*)は遅いのか?COUNT(列名)は速いのか?~実行計画を確認~

前回は、COUNT(*)が必ずしも遅いわけではないことはおわかり頂けたと思います。
もう一つ検証したいポイントがあります。
よく言われている「COUNT(*)は全表走査(FULLSCAN)になるので遅い」という点です。

試しに前回実行した次のSQLの実行計画を取得してみましょう。
前回と同様に、COUNT(*)を取得するだけのシンプルなSQLで確認してみます。

SELECT COUNT(*) FROM pt_count_test;

COUNT(*)で抽出条件もない場合の実行計画

続いては、COUNT(PK列)の場合の実行計画を見てみましょう。

SELECT COUNT(pkid) FROM pt_count_test;

COUNT(PK列)で抽出条件もない場合の実行計画

いずれも同じ実行計画(FAST FULL SCAN)になりました。
COUNT(*)を使ったからと言ってFULL SCANになるわけではないようです。

これまではWHERE句なしのSQLばかりでしたが、実行計画はWHERE句で決まるもの。
WHERE句を入れてみましょう。
抽出条件はval2とval3いずれもINDEXが貼られていない列で、COUNT(*)とCOUNT(PK列)の比較です。
まずは、val2を抽出条件にCOUNT(*)を使用した場合。

SELECT COUNT(*) FROM pt_count_test WHERE LENGTH(val2) > 500;

COUNT(*)でWHERE句が入っている場合(INDEXなし)

そして、val3を抽出条件にCOUNT(PK列)を使用した場合。

SELECT COUNT(pkid) FROM pt_count_test WHERE LENGTH(val3) > 500;

COUNT(PK列)でWHERE句が入っている場合(INDEXなし)

やはり抽出条件が同じであればCOUNT(*)かCOUNT(列名)かで、実行計画が変わることは無いようです。
ここでは、抽出条件がINDEXの無い列ですので、共にFULLSCANになります。

次は抽出条件にプライマリキー項目を使用してみましょう。

SELECT COUNT(*) FROM pt_count_test WHERE pkid >=0;

COUNT(*)でWHERE句が入っている場合(INDEX使用)

SELECT COUNT(pkid) FROM pt_count_test WHERE pkid >=0;

COUNT(PK列)でWHERE句が入っている場合(INDEX使用)

やはり、COUNT(*)とCOUNT(PK列)の違いで実行計画は変わらないですね。

ということですので、安心してCOUNT(*)をご使用ください。

2018-09-18Oracle,パフォーマンスcount,Oracle,PL/SQL,SQL,パフォーマンス

Posted by tfurukaw