Oracle 10gのSQL*Plusで実行計画を取得する
オブジェクトブラウザのようなソフトを使って実行計画を取得することはときどきあるけど、SQL*Plusでやったことがなかったので試してみた。次のサイトの記事を参考にした。
使っているのはOracle 10g Express Edition (XE)。
下準備が必要
以下のサイトを参考にして下準備した。
SQL*Plusで実行計画を取得する - オラクル・Oracle SQL*Plus リファレンス
以下の順序で進める。特に問題になる箇所はなかった。
実行計画を取得する
こんな感じのデータがある。
SQL> select * from products; CODE PRICE ---- ---------- AA01 100 BB01 200 BB02 200 DD02 300 SQL> spool off
PRICEの値が重複していない行だけを取り出したい。
比較したい2つのSQLの実行計画を順次取得する。
spool trace.log set lines 200 col plan_plus_exp format a200 set pages 0 set autotrace on SELECT A.CODE, A.PRICE FROM PRODUCTS A WHERE A.PRICE IN ( SELECT B.PRICE FROM PRODUCTS B GROUP BY B.PRICE HAVING COUNT('X') = 1 ) ORDER BY 1; SELECT MIN(code),price FROM products GROUP BY price HAVING COUNT(*)=1 ORDER BY 1; spool off
得られた結果が次のようなものだった。
まずひとつめのSQLの結果。
実行計画 ---------------------------------------------------------- Plan hash value: 3428268735 ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 120 | 9 (34)| 00:00:01 | | 1 | SORT ORDER BY | | 4 | 120 | 9 (34)| 00:00:01 | |* 2 | HASH JOIN SEMI | | 4 | 120 | 8 (25)| 00:00:01 | | 3 | TABLE ACCESS FULL | PRODUCTS | 4 | 68 | 3 (0)| 00:00:01 | | 4 | VIEW | VW_NSO_1 | 4 | 52 | 4 (25)| 00:00:01 | |* 5 | FILTER | | | | | | | 6 | HASH GROUP BY | | 4 | 52 | 4 (25)| 00:00:01 | | 7 | TABLE ACCESS FULL| PRODUCTS | 4 | 52 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("A"."PRICE"="$nso_col_1") 5 - filter(COUNT(*)=1) Note ----- - dynamic sampling used for this statement 統計 ---------------------------------------------------------- 78 recursive calls 0 db block gets 98 consistent gets 0 physical reads 0 redo size 534 bytes sent via SQL*Net to client 384 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 5 sorts (memory) 0 sorts (disk) 2 rows processed
これが2つめのSQLの結果。
実行計画 ---------------------------------------------------------- Plan hash value: 1002956361 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 68 | 5 (40)| 00:00:01 | | 1 | SORT ORDER BY | | 4 | 68 | 5 (40)| 00:00:01 | |* 2 | FILTER | | | | | | | 3 | HASH GROUP BY | | 4 | 68 | 5 (40)| 00:00:01 | | 4 | TABLE ACCESS FULL| PRODUCTS | 4 | 68 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(COUNT(*)=1) Note ----- - dynamic sampling used for this statement 統計 ---------------------------------------------------------- 5 recursive calls 0 db block gets 15 consistent gets 0 physical reads 0 redo size 539 bytes sent via SQL*Net to client 384 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 2 rows processed
これを読み解くのにまた一苦労だなあ。一見すると2つめのほうがよいパフォーマンスであるようにみえる。