在12C中,cbo會自動改寫標量子查詢了:
create table test as select * frm dba_objects;
create table test3 as select * from test;
select (select max(DATA_OBJECT_ID) from test b where b.object_id=a.object_id ) from test3 a;
該語句在11G中的plan爲
Plan Hash Value :
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 94599 | 1229787 | 347 | 00:00:05 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| * 2 | TABLE ACCESS FULL | TEST | 870 | 22620 | 347 | 00:00:05 |
| 3 | TABLE ACCESS FULL | TEST3 | 94599 | 1229787 | 347 | 00:00:05 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - filter("B"."OBJECT_ID"=:B1)
而在12C中被CBO改寫成了left join
如果把max改成rownum <=1,cbo不會進行改寫
如果同時用了max與rownum<=1 就會出現錯誤的plan和結果
SQL> explain plan for select (select max(b.DATA_OBJECT_ID) from test b where b.object_id=a.object_id and rownum=1) from test3 a;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------
Plan hash value: 730023338
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 91583 | 2772K| 412 (1)| 00:00:01 |
|* 1 | HASH JOIN RIGHT OUTER | | 91583 | 2772K| 412 (1)| 00:00:01 |
| 2 | VIEW | VW_SSQ_1 | 1 | 26 | 2 (50)| 00:00:01 |
| 3 | HASH GROUP BY | | 1 | 7 | 2 (50)| 00:00:01 |
|* 4 | COUNT STOPKEY | | | | | |
| 5 | TABLE ACCESS INMEMORY FULL| TEST | 1 | 7 | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | TEST3 | 91583 | 447K| 410 (1)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("ITEM_1"(+)="A"."OBJECT_ID")
4 - filter(ROWNUM=1)
19 rows selected.
當然,幾乎沒人同時用max和rownum的