SELECT COUNT(*)は処理速度が遅くなるから、SELECT COUNT(1)を使った方が良いと聞きます。
SELECT COUNT(*)で全カラムを指定するよりも、SELECT COUNT(1)を使って、Praimary Key(インデックス)である1カラム目を指定した方が速いという理屈は理解できます。
そこでですが、SELECT COUNT(1)は本当に処理速度が速いのか検証してみました。
SELECT COUNT(*)とSELECT COUNT(1)の性能検証
TB_MAINテーブルには100万件のレコードが登録されており2カラムあります。
TB_MAINテーブルの1カラム目(ID)はPRAYMARY_KEYです。
性能測定なのでクエリの実行前に共有プールのクリアとデータベース・バッファ・キャッシュのクリアもしています。
DESC TB_MAIN; 名前 NULL? 型 -------- -------- ------------------ ID NOT NULL NUMBER(8) NAME VARCHAR2(10 CHAR)SELECT COUNT(*) FROM TB_MAIN; COUNT(*) ---------- 1000000 経過: 00:00:03.16SELECT COUNT(1) FROM TB_MAIN; COUNT(1) ---------- 1000000 経過: 00:00:04.43
試してみたらSELECT COUNT(1)の方が遅いですね。それぞれの実行計画も確認しました。
SELECT COUNT(*)の実行計画と統計
SELECT COUNT(*) FROM TB_MAIN; 経過: 00:00:00.10 実行計画 ---------------------------------------------------------- Plan hash value: 3829837348 ----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 571 (1)| 00:00:07 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| SYS_C007642 | 1000K| 571 (1)| 00:00:07 | ----------------------------------------------------------------------------- 統計 ----------------------------------------------------------1 recursive calls0 db block gets 2101 consistent gets 0 physical reads 0 redo size 549 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
SELECT COUNT(1)の実行計画と統計
SELECT COUNT(1) FROM TB_MAIN; 経過: 00:00:00.09 実行計画 ---------------------------------------------------------- Plan hash value: 3829837348 ----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 571 (1)| 00:00:07 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| SYS_C007642 | 1000K| 571 (1)| 00:00:07 | ----------------------------------------------------------------------------- 統計 ----------------------------------------------------------0 recursive calls0 db block gets 2101 consistent gets 0 physical reads 0 redo size 549 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
実行計画はどちらも同じですが、統計はSELECT COUNT(*)の場合、recursive callsが1となっており、SELECT COUNT(1)の場合、recursive callsが0となっています。
recursive calls(再帰的コールの回数)の数値が高ければ、遅いSQLになると思っていましたが、recursive callsの数値が高ければ、速くなるという不思議な結果となりました。
SELECT COUNT(*)にした方がORACLEオプティマイザがSQLを最適化してくれているという考え方もできますが、どうなんでしょうか!?
結果は少し納得ができなかったので、次回はデータ件数やカラム数を増やして検証していきたいと思います。
以上です。