Analyticsを使用して、DISTINCT演算子を適用が進むべき道ではない、あなたが集計する必要がある場合。
SQL> select a.id
2 , max(t.type_id) keep (dense_rank last order by t.create_date) max_create_date_type_id
3 , max(a.assign_id) keep (dense_rank last order by t.create_date) assign_id
4 from assignment a
5 , type t
6 where a.type_id = t.type_id
7 group by a.id
8/
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
1x 3 664
2x 4 514
2 rows selected.
そして、ここではそれがよりパフォーマンスだことを証明するための試験である:ここで
のみ集計使用して、より簡単でパフォーマンスバージョンである
SQL> exec dbms_stats.gather_table_stats(user,'assignment')
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'type')
PL/SQL procedure successfully completed.
SQL> select /*+ gather_plan_statistics */
2 distinct
3 a.id,
4 first_value(t.type_id)
5 over (partition by a.id order by t.create_date desc)
6 as max_create_date_type_id,
7 first_value(a.assign_id)
8 over (partition by a.id order by t.create_date desc)
9 as assign_id
10 from assignment a, type t
11 where a.type_id = t.type_id
12/
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
2x 4 514
1x 3 664
2 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
2/
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------
SQL_ID fu520w4kf2bbp, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ distinct a.id,
first_value(t.type_id) over (partition by a.id order by
t.create_date desc) as max_create_date_type_id,
first_value(a.assign_id) over (partition by a.id order by
t.create_date desc) as assign_id from assignment a, type t where
a.type_id = t.type_id
Plan hash value: 4160194652
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 6 | | | |
| 1 | HASH UNIQUE | | 1 | 4 | 2 |00:00:00.01 | 6 | 898K| 898K| 493K (0)|
| 2 | WINDOW SORT | | 1 | 4 | 4 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
| 3 | WINDOW SORT | | 1 | 4 | 4 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
|* 4 | HASH JOIN | | 1 | 4 | 4 |00:00:00.01 | 6 | 898K| 898K| 554K (0)|
| 5 | TABLE ACCESS FULL| ASSIGNMENT | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
| 6 | TABLE ACCESS FULL| TYPE | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("A"."TYPE_ID"="T"."TYPE_ID")
28 rows selected.
SQL> select /*+ gather_plan_statistics */
2 a.id
3 , max(t.type_id) keep (dense_rank last order by t.create_date) max_create_date_type_id
4 , max(a.assign_id) keep (dense_rank last order by t.create_date) assign_id
5 from assignment a
6 , type t
7 where a.type_id = t.type_id
8 group by a.id
9/
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
1x 3 664
2x 4 514
2 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
2/
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------
SQL_ID 156kpxgxmfjd3, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ a.id , max(t.type_id)
keep (dense_rank last order by t.create_date) max_create_date_type_id
, max(a.assign_id) keep (dense_rank last order by t.create_date)
assign_id from assignment a , type t where a.type_id =
t.type_id group by a.id
Plan hash value: 3494156172
-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 6 | | | |
| 1 | SORT GROUP BY | | 1 | 2 | 2 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
|* 2 | HASH JOIN | | 1 | 4 | 4 |00:00:00.01 | 6 | 898K| 898K| 594K (0)|
| 3 | TABLE ACCESS FULL| ASSIGNMENT | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
| 4 | TABLE ACCESS FULL| TYPE | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
-----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."TYPE_ID"="T"."TYPE_ID")
25 rows selected.
あなたが見ることができるように、両方のフルスキャンしていますテーブルとハッシュジョインを実行します。違いはこのステップ後です。集約バリアントは、SORT GROUP BYを使用して4行を集め、2行に集約します。分析的なものは、最初に4行セットを2回ソートしてから、HASH UNIQUEを適用して2行に減らします。
よろしく、 ロブ。
ありがとうございます。 私はfirst_valueとoverコマンドについて聞いたことがありません。 – AlteredConcept
「Oracleの分析機能」を参照してください - 非常に強力です:)推奨読書:http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions001.htm#i81407 –
が修正されました。ヴィンセントの答えを読む。 –