Oracle 11gを使用しています。メイン表には約10mのレコードがあります。ここに私のクエリは次のとおりです。COUNT()でのOracleパフォーマンスの問題
SELECT COUNT (*)
FROM CONTACT c INNER JOIN STATUS S ON C.STATUS = S.STATUS
WHERE C.USER = 1 AND S.REQUIRE = 1 AND ROWNUM = 1;
コストは3736ですが、私はこのフォームにそれを変更する場合:
SELECT COUNT (*) FROM
(SELECT 1 FROM CONTACT c INNER JOIN STATUS S ON C.STATUS = S.STATUS
WHERE C.USER = 1 AND S.REQUIRE = 1 AND ROWNUM = 1);
コストは5になりました!これら2つのクエリの違いは何ですか?ここで
は、両方のクエリのための計画を説明している:最初のクエリ:
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 3736 (1)| 00:00:45 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | NESTED LOOPS | | 4627 | 46270 | 3736 (1)| 00:00:45 |
| 4 | TABLE ACCESS BY INDEX ROWID| CONTACT | 6610 | 33050 | 3736 (1)| 00:00:45 |
|* 5 | INDEX RANGE SCAN | IX_CONTACT_USR | 6610 | | 20 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IX_CONTACT_STATUS | 1 | 5 | 0 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM=1)
5 - access("C"."USER"=1)
6 - access("C"."STATUS"="S"."STATUS" AND "S"."REQUIRE"=1)
2番目のクエリ:
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | | |
| 2 | VIEW | | 1 | | 5 (0)| 00:00:01 |
|* 3 | COUNT STOPKEY | | | | | |
| 4 | NESTED LOOPS | | 2 | 20 | 5 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| CONTACT | 3 | 15 | 5 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IX_CONTACT_USR | 6610 | | 3 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | IX_CONTACT_STATUS | 1 | 5 | 0 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(ROWNUM=1)
6 - access("C"."USER"=1)
7 - access("C"."STATUS"="S"."STATUS" AND "S"."REQUIRE"=1)
私は2つのクエリを実行し、最初の1時にはコストの45S + (例えば、最初に実行するか、ユーザーIDを変更する)、それ以外の場合は、<になります。私はまったく違うのか、おそらくdbキャッシュなのか全く分かりません。
私が2番目のクエリを実行したとき、私はいつも1で結果を得ることができます。だから、私は2番目の方が良いと思うが、それがたくさん改善する理由はない。
提供される説明計画についてのコメント:私が想定したように、あなたの2つのクエリーは異なるものではありません。唯一の違いは2行目で、それはパフォーマンスに影響しません...(また、実行計画では必ずしも実行計画に収まるものではないことに気がつくので、私はそれをトレースするように提案しています) – igr
良い質問と間違いなく別の回答!私はあなたが多くのことをしていない計画を入れてうれしく思います。 – glh
両方のクエリの説明計画を投稿すると、テーブルの統計情報をよりよく理解し、2つのクエリを比較するのに役立ちます。 http://www.oraclebin.com/2012/12/explain-plan-how-to-get-execution-plan.htmlあなたは彼らが実際の異なる量で実行 –