botang 发表于 2022-5-15 17:17:57

SQL改写案例

oradebug setospid 45744416
oradebug unlimit
oradebug event 10053 trace name context forever,level 1

SELECT ch.channel_class, c.cust_city, t.calendar_quarter_desc,
SUM(s.amount_sold) sales_amount
FROM
sh.sales s,sh.times t,sh.customers c,sh.channels ch
WHERE s.time_id = t.time_id AND
s.cust_id = c.cust_id AND
s.channel_id = ch.channel_id AND
c.cust_state_province = 'CA' AND
ch.channel_desc IN ('Internet','Catalog') AND
t.calendar_quarter_desc IN ('2002-01','2002-02')
GROUP BY ch.channel_class, c.cust_city, t.calendar_quarter_desc;
alter session set events '10053 trace name context forever, level 1';
1. 特别简单又容易忽视的场景:
准备环境:
SQL> create table t3( avarchar2(20)) ;
Table created.
SQL> begin
2   for i in 1..100000
3   loop
4    insert into t3 values(to_char(i));
5   end loop;
6   commit;
7end;
8/
PL/SQL procedure successfully completed.

SQL> create index i3 on t3(a) ;
Index created.
测试执行计划1:
SQL> set autot on
SQL> select * from t3 where a=999;
A
--------------------
999
Execution Plan
----------------------------------------------------------
Plan hash value: 4161002650
--------------------------------------------------------------------------
| Id| Operation          | Name | Rows| Bytes | Cost (%CPU)| Time         |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT|         |   3 |    36 |    69   (2)| 00:00:01 |
|*1 |TABLE ACCESS FULL| T3         |   3 |    36 |    69   (2)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("A")=999)
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold

Statistics
----------------------------------------------------------
          8recursive calls
          5db block gets
      243consistent gets
          0physical reads
       1008redo size
      544bytes sent via SQL*Net to client
      390bytes received via SQL*Net from client
          2SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
          1rows processed
测试执行计划2:
SQL> select * from t3 where a='999';
A
--------------------
999
Execution Plan
----------------------------------------------------------
Plan hash value: 2553414617
-------------------------------------------------------------------------
| Id| Operation         | Name | Rows      | Bytes | Cost (%CPU)| Time      |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT |      |   1 |    12 |   1   (0)| 00:00:01 |
|*1 |INDEX RANGE SCAN| I3      |   1 |    12 |   1   (0)| 00:00:01 |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("A"='999')
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
Statistics
----------------------------------------------------------
          9recursive calls
          0db block gets
         52consistent gets
          1physical reads
          0redo size
      544bytes sent via SQL*Net to client
      392bytes received via SQL*Net from client
          2SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
          1rows processed

2. 关联子查询改写(顺便研究sql 10046 trace):
LISTPRICE_RELATE的trace:
SQL> conn sh/oracle_4U@rcat
Connected.
SQL> alter session set tracefile_identifier='LISTPRICE_RELATE';
Session altered.
SQL> alter session set sql_trace=true;
Session altered.
SQL> select /*LISTJOIN_RELATE*/ count(*) from products p
   wherep.prod_list_price < 1.15*(selectavg(unit_cost) avg from costs c
                                                          where c.prod_id=p.prod_id);2    3
COUNT(*)
----------
      46
SQL>alter session set sql_trace=false;
Session altered.
LISTPRICE_JOIN的trace:
SQL> conn sh/oracle_4U@rcat
Connected.
SQL> alter session set tracefile_identifier='LISTPRICE_JOIN';
Session altered.
SQL> alter session set sql_trace=true;
Session altered.
SQL> select /*LISTPRICE_JOIN*/ count(*)from products p,
(selectprod_id,avg(unit_cost) avg from costsgroup by prod_id) a
where p.prod_id=a.prod_id and
             p.prod_list_price < 1.15* a.avg;2    3    4
COUNT(*)
----------
      46
SQL>alter session set    sql_trace=false;
Session altered.
/u01/app/oracle/diag/rdbms/rcat/rcat/trace:
$ ls *LISTPRICE*
rcat_ora_1519515_LISTPRICE_RELATE.trcrcat_ora_1536602_LISTPRICE_JOIN.trc
rcat_ora_1519515_LISTPRICE_RELATE.trmrcat_ora_1536602_LISTPRICE_JOIN.trm
trcsess合并:
$ trcsess output=/home/oracle/LISTPRICE.trc service=rcat.example.com rcat_ora_1519515_LISTPRICE_RELATE.trc rcat_ora_1536602_LISTPRICE_JOIN.trc
tkprof解读:
$ tkprof /home/oracle/LISTPRICE.trc /home/oracle/report.txt explain=sh/oracle_4U@rcat
********************************************************************************

select /*LISTPRICE_JOIN*/ count(*)from products p,
(selectprod_id,avg(unit_cost) avg from costsgroup by prod_id) a
where p.prod_id=a.prod_id and
             p.prod_list_price < 1.15* a.avg

call   count       cpu    elapsed       disk      query    current      rows
------- -------------- ---------- ---------- ---------- --------------------
Parse      1      0.03       0.03          0       2778          0         0
Execute      1      0.00       0.00          0          0          0         0
Fetch      2      0.00       0.00          0         19          0         1
------- -------------- ---------- ---------- ---------- --------------------
total      4      0.04       0.04          0       2797          0         1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 105(SH)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)Row Source Operation
---------- ---------- -------------------------------------------------------------
         1          1          1SORT AGGREGATE (cr=68 pr=0 pw=0 time=11765 us starts=1)
      46         46         46   HASH JOIN(cr=68 pr=0 pw=0 time=11773 us starts=1 cost=17 size=140 card=4)
      72         72         72    TABLE ACCESS FULL PRODUCTS (cr=3 pr=0 pw=0 time=81 us starts=1 cost=3 size=648 card=72)
      72         72         72    VIEW(cr=16 pr=0 pw=0 time=6535 us starts=1 cost=14 size=1872 card=72)
      72         72         72   HASH GROUP BY (cr=16 pr=0 pw=0 time=6521 us starts=1 cost=14 size=648 card=72)
      1068       1068       1068      PARTITION RANGE ALL PARTITION: 1 28 (cr=16 pr=0 pw=0 time=7629 us starts=1 cost=13 size=739008 card=82112)
      1068       1068       1068       TABLE ACCESS INMEMORY FULL COSTS PARTITION: 1 28 (cr=16 pr=0 pw=0 time=5671 us starts=28 cost=13 size=739008 card=82112)


Rows   Execution Plan
----------------------------------------------------------
      0SELECT STATEMENT   MODE: ALL_ROWS
      1   SORT (AGGREGATE)
   46    HASH JOIN
   72   TABLE ACCESS   MODE: ANALYZED (FULL) OF 'PRODUCTS' (TABLE)
   72   VIEW
   72      HASH (GROUP BY)
   1068       PARTITION RANGE (ALL) PARTITION: START=1 STOP=28
   1068      TABLE ACCESS   MODE: ANALYZED (INMEMORY FULL) OF
                   'COSTS' (TABLE) PARTITION: START=1 STOP=28

********************************************************************************

select /*LISTJOIN_RELATE*/ count(*) from products p
   wherep.prod_list_price < 1.15*(selectavg(unit_cost) avg from costs c
                                                          where c.prod_id=p.prod_id)

call   count       cpu    elapsed       disk      query    current      rows
------- -------------- ---------- ---------- ---------- --------------------
Parse      1      0.01       0.01          0         58          0         0
Execute      1      0.00       0.00          0          0          0         0
Fetch      2      0.00       0.00          0         19          0         1
------- -------------- ---------- ---------- ---------- --------------------
total      4      0.02       0.02          0         77          0         1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 105(SH)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)Row Source Operation
---------- ---------- -------------------------------------------------------------
         1          1          1SORT AGGREGATE (cr=19 pr=0 pw=0 time=7879 us starts=1)
      46         46         46   HASH JOIN(cr=19 pr=0 pw=0 time=7882 us starts=1 cost=17 size=140 card=4)
      72         72         72    NESTED LOOPS(cr=16 pr=0 pw=0 time=7567 us starts=1 cost=17 size=140 card=4)
      72         72         72   NESTED LOOPS(cr=16 pr=0 pw=0 time=7493 us starts=1)
      72         72         72      STATISTICS COLLECTOR(cr=16 pr=0 pw=0 time=7490 us starts=1)
      72         72         72       VIEWVW_SQ_1 (cr=16 pr=0 pw=0 time=7381 us starts=1 cost=14 size=1872 card=72)
      72         72         72      HASH GROUP BY (cr=16 pr=0 pw=0 time=7362 us starts=1 cost=14 size=648 card=72)
      1068       1068       1068         PARTITION RANGE ALL PARTITION: 1 28 (cr=16 pr=0 pw=0 time=8594 us starts=1 cost=13 size=739008 card=82112)
      1068       1068       1068          TABLE ACCESS INMEMORY FULL COSTS PARTITION: 1 28 (cr=16 pr=0 pw=0 time=6363 us starts=28 cost=13 size=739008 card=82112)
         0          0          0      INDEX UNIQUE SCAN PRODUCTS_PK (cr=0 pr=0 pw=0 time=0 us starts=0)(object id 92749)
         0          0          0   TABLE ACCESS BY INDEX ROWID PRODUCTS (cr=0 pr=0 pw=0 time=0 us starts=0 cost=3 size=9 card=1)
      72         72         72    TABLE ACCESS FULL PRODUCTS (cr=3 pr=0 pw=0 time=46 us starts=1 cost=3 size=648 card=72)


Rows   Execution Plan
----------------------------------------------------------
      0SELECT STATEMENT   MODE: ALL_ROWS
      1   SORT (AGGREGATE)
   46    HASH JOIN
   72   NESTED LOOPS
   72      NESTED LOOPS
   72       STATISTICS COLLECTOR
   72      VIEW OF 'VW_SQ_1' (VIEW)
   72         HASH (GROUP BY)
   1068          PARTITION RANGE (ALL) PARTITION: START=1 STOP=28
   1068         TABLE ACCESS   MODE: ANALYZED (INMEMORY FULL) OF
                      'COSTS' (TABLE) PARTITION: START=1 STOP=28
      0       INDEX   MODE: ANALYZED (UNIQUE SCAN) OF 'PRODUCTS_PK'
                  (INDEX (UNIQUE))
      0      TABLE ACCESS   MODE: ANALYZED (BY INDEX ROWID) OF
               'PRODUCTS' (TABLE)
   72   TABLE ACCESS   MODE: ANALYZED (FULL) OF 'PRODUCTS' (TABLE)

********************************************************************************
SQL>select 'OK' from dual where exists (select a from t3 where rownum=1);
'O
--
OK
Execution Plan
----------------------------------------------------------
Plan hash value: 1170111551
--------------------------------------------------------------------
| Id| Operation            | Name | Rows| Cost (%CPU)| Time         |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |         1 |         4   (0)| 00:00:01 |
|*1 |FILTER             |         |         |                |         |
|   2 |   FAST DUAL            |         |         1 |         2   (0)| 00:00:01 |
|*3 |   COUNT STOPKEY   |         |         |                |         |
|   4 |    TABLE ACCESS FULL| T3   | 81798 |         2   (0)| 00:00:01 |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( EXISTS (SELECT 0 FROM "T3" "T3" WHERE ROWNUM=1))
   3 - filter(ROWNUM=1)
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
Statistics
----------------------------------------------------------
          7recursive calls
          0db block gets
          8consistent gets
          0physical reads
          0redo size
      546bytes sent via SQL*Net to client
      431bytes received via SQL*Net from client
          2SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
          1rows processed
SQL> select 'OK' from dual where (selectcount(*) from t3) >=1 ;
'O
--
OK
Execution Plan
----------------------------------------------------------
Plan hash value: 1926481175
--------------------------------------------------------------------
| Id| Operation            | Name | Rows| Cost (%CPU)| Time         |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |         1 |      70   (0)| 00:00:01 |
|*1 |FILTER             |         |         |                |         |
|   2 |   FAST DUAL            |         |         1 |         2   (0)| 00:00:01 |
|   3 |   SORT AGGREGATE    |         |         1 |                |         |
|   4 |    TABLE ACCESS FULL| T3   | 81798 |      68   (0)| 00:00:01 |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( (SELECT COUNT(*) FROM "T3" "T3")>=1)
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
Statistics
----------------------------------------------------------
          4recursive calls
          0db block gets
      193consistent gets
          0physical reads
          0redo size
      546bytes sent via SQL*Net to client
      421bytes received via SQL*Net from client
          2SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
          1rows processed

3 . with clause:
SQL> set linesize 10000
SQL> set autot traceonly
SQL> select prod_id, amount_sold from sales
2   where amount_sold= (select max(amount_sold) from sales)
3union all
4select prod_id, amount_sold from sales
5   where amount_sold= (select min(amount_sold) from sales)
6union all
7select prod_id, amount_sold from sales
8   where amount_sold= (select avg(amount_sold) from sales)
9;

292 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3943716753

-------------------------------------------------------------------------------------------------
| Id| Operation               | Name| Rows| Bytes | Cost (%CPU)| Time   | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |1536 | 13824 | 26734   (1)| 00:00:02 |       |       |
|   1 |UNION-ALL            |       |       |       |            |          |       |       |
|   2 |   PARTITION RANGE ALL   |       |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|*3 |    TABLE ACCESS FULL    | SALES |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|   4 |   SORT AGGREGATE      |       |   1 |   5 |            |          |       |       |
|   5 |      PARTITION RANGE ALL|       |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|   6 |       TABLE ACCESS FULL | SALES |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|   7 |   PARTITION RANGE ALL   |       |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|*8 |    TABLE ACCESS FULL    | SALES |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|   9 |   SORT AGGREGATE      |       |   1 |   5 |            |          |       |       |
|10 |      PARTITION RANGE ALL|       |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|11 |       TABLE ACCESS FULL | SALES |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|12 |   PARTITION RANGE ALL   |       |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|* 13 |    TABLE ACCESS FULL    | SALES |   512 |4608 |4457   (1)| 00:00:01 |   1 |    28 |
|14 |   SORT AGGREGATE      |       |   1 |   5 |            |          |       |       |
|15 |      PARTITION RANGE ALL|       |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|16 |       TABLE ACCESS FULL | SALES |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("AMOUNT_SOLD"= (SELECT MAX("AMOUNT_SOLD") FROM "SALES" "SALES"))
   8 - filter("AMOUNT_SOLD"= (SELECT MIN("AMOUNT_SOLD") FROM "SALES" "SALES"))
13 - filter("AMOUNT_SOLD"= (SELECT AVG("AMOUNT_SOLD") FROM "SALES" "SALES"))

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold


Statistics
----------------------------------------------------------
          0recursive calls
          0db block gets
      39680consistent gets
          0physical reads
          0redo size
       5765bytes sent via SQL*Net to client
      761bytes received via SQL*Net from client
         21SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
      292rows processedSQL> with s as ( selectmax(amount_sold) max,
2                      min(amount_sold) min,
3                      avg(amount_sold) avg
4             from sales)
5select prod_id, amount_sold from sales
6   where amount_sold in (selectmax from s union all selectmin from s union all select avg from s )
7;

292 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2588622809

------------------------------------------------------------------------------------------------------------------------
| Id| Operation                  | Name                      | Rows| Bytes | Cost (%CPU)| Time   | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |                           |1537 | 33814 |8920   (1)| 00:00:01 |       |       |
|   1 |TEMP TABLE TRANSFORMATION |                           |       |       |            |          |       |       |
|   2 |   LOAD AS SELECT         | SYS_TEMP_0FD9D663D_1F26D4 |       |       |            |          |       |       |
|   3 |    SORT AGGREGATE          |                           |   1 |   5 |            |          |       |       |
|   4 |   PARTITION RANGE ALL    |                           |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|   5 |      TABLE ACCESS FULL   | SALES                     |1837K|8973K|4454   (1)| 00:00:01 |   1 |    28 |
|*6 |   HASH JOIN                |                           |1537 | 33814 |4465   (1)| 00:00:01 |       |       |
|   7 |    VIEW                  | VW_NSO_1                  |   3 |    39 |   6   (0)| 00:00:01 |       |       |
|   8 |   HASH UNIQUE            |                           |   3 |    39 |   6   (0)| 00:00:01 |       |       |
|   9 |      UNION-ALL             |                           |       |       |            |          |       |       |
|10 |       VIEW               |                           |   1 |    13 |   2   (0)| 00:00:01 |       |       |
|11 |      TABLE ACCESS FULL   | SYS_TEMP_0FD9D663D_1F26D4 |   1 |   5 |   2   (0)| 00:00:01 |       |       |
|12 |       VIEW               |                           |   1 |    13 |   2   (0)| 00:00:01 |       |       |
|13 |      TABLE ACCESS FULL   | SYS_TEMP_0FD9D663D_1F26D4 |   1 |   5 |   2   (0)| 00:00:01 |       |       |
|14 |       VIEW               |                           |   1 |    13 |   2   (0)| 00:00:01 |       |       |
|15 |      TABLE ACCESS FULL   | SYS_TEMP_0FD9D663D_1F26D4 |   1 |   5 |   2   (0)| 00:00:01 |       |       |
|16 |    PARTITION RANGE ALL   |                           |1837K|    15M|4454   (1)| 00:00:01 |   1 |    28 |
|17 |   TABLE ACCESS FULL      | SALES                     |1837K|    15M|4454   (1)| 00:00:01 |   1 |    28 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("AMOUNT_SOLD"="MAX")

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold


Statistics
----------------------------------------------------------
          2recursive calls
          8db block gets
      13251consistent gets
          1physical reads
      624redo size
       6707bytes sent via SQL*Net to client
      761bytes received via SQL*Net from client
         21SQL*Net roundtrips to/from client
          0sorts (memory)
          0sorts (disk)
      292rows processed
4. merge:
SQL> create table t1 (a varchar2(20), b number);
Table created.
SQL> create table t2 (a varchar2(20), b number);
Table created.
SQL> insert into t1 values('a', 1) ;   
1 row created.
SQL> insert into t1 values('b', 2);
1 row created.
SQL> insert into t1 values('c', 3);
1 row created.
SQL>insert into t1 values('xxx',100);
1 row created.
SQL> insert into t1 values('yyy',200);
1 row created.
SQL> commit;
Commit complete.
SQL> insert into t2 values ('a',10);
1 row created.
SQL> insert into t2 values ('b',20);
1 row created.
SQL> insert into t2 values ('xxx',30);
1 row created.
SQL> insert into t2 values ('yyy',40);
1 row created.
SQL> commit;
Commit complete.

merge into t2
using t1
on (t1.a=t2.a)
when matched then
update
set t2.b=t1.b*2
merge into t2
using t1
on (t1.a=t2.a)
when matched then
update
set t2.b=t1.b*2
where t1.a='xxx'

merge into t2
using t1
on (t1.a=t2.a)
when matched then
update
set t2.b=t1.b*2
delete where t2.a='yyy'

merge into t2
using t1
on (1<>1)
when not matched then
insert
values (t1.a, t1.b)


页: [1]
查看完整版本: SQL改写案例