SlideShare a Scribd company logo
1 of 63
Download to read offline
Some SQL Techniques
Who am I

           •  Been with Oracle since
              1993
           •  User of Oracle since 1987
           •  The “Tom” behind AskTom
              in Oracle Magazine
               www.oracle.com/oramag
           •  Expert Oracle Database
              Architecture
           •  Effective Oracle by Design
           •  Expert One on One Oracle
           •  Beginning Oracle
Agenda

•  What do you need to write “good” SQL
•  The Schema Matters
•  Knowing what is available
    –    Using rownum (yes, to 'tune')
    –    Scalar subqueries
    –    Analytics
    –    Some hints
•  Don’t tune queries!
•  Other things
    –    Materialized Views
    –    With subquery factoring
    –    Merge
    –    …
What do you need to know…

•  Access Paths
     –    There are a lot of them
     –    There is no best one (else there would be, well, one)
•  A little bit of physics
     –    Full scans are not evil
     –    Indexes are not all goodness
•  How the data is managed by Oracle
     –    high water marks for example
     –    IOT’s, clusters, etc
•  What your query needs to actually do
     –    Is that outer join really necessary or “just in case”
Structures

   •  How the data is accessed and organized
      makes a difference
           –    Clustering



Select *
from orders o, line_items li
                               ORDERS ORDERS & LINE
where o.order# = li.order#           LINE ITEMS
                                              ITEMS
And o.order# = :order
Structures

     •  How the data is accessed and organized
        makes a difference
          –    Clustering
          –    Index Organized Tables


Select avg(price)                       STOCKS
                                        STOCKS
From stocks
Where symbol = ‘ORCL’
And stock_dt >= sysdate-5;
Structures

   •  How the data is accessed and organized
      makes a difference
      –    Clustering
      –    Index Organized Tables       ORDERS
                                       ORDERS
                                         ORDERS
      –    Partitioning                              Europe

                                                     USA
                                     Jan
                                      Jan Feb Feb
                                    Composite Partition
                                    Partition
                                    Large Table
                                    Higher and Manage
                                    Divide Performance
                                    Difficult to Conquer
                                    More flexibility to match
                                    Easier to Manage
                                    business needs
                                    Improve Performance
The Schema Matters

•  A Lot!
•  Tune this query:
    Select DOCUMENT_NAME, META_DATA
      from documents
     where userid=:x;
•  That is about as easy as it gets (the SQL)
•  Not too much we can do to rewrite it…
•  But we’d like to make it better.
                                                Iot01.sql
                                                  Cf.sql
Organization Counts

ops$tkyte%ORA11GR2> create table iot
  2 ( username          varchar2(30),
  3    document_name    varchar2(30),
  4    other_data       char(1000),
  5    constraint iot_pk primary key (username,document_name))
  6 organization index
  7 /
Table created.

ops$tkyte%ORA11GR2> create table heap
  2 ( username          varchar2(30),
  3    document_name    varchar2(30),
  4    other_data       char(1000),
  5    constraint heap_pk primary key (username,document_name))
  6 /
Table created.
Organization Counts
ops$tkyte%ORA11GR2> begin
  2      for i in 1 .. 100
  3      loop
  4           for x in ( select username from all_users )
  5           loop
  6                insert into heap
  7                (username,document_name,other_data) values
  8                ( x.username, x.username || '_' || i, 'x' );
  9
 10                insert into iot
 11                (username,document_name,other_data) values
 12                ( x.username, x.username || '_' || i, 'x' );
 13           end loop;
 14      end loop;
 15      dbms_stats.gather_table_stats
 16      ( user, 'IOT', cascade=>true );
 17      dbms_stats.gather_table_stats
 18      ( user, 'HEAP', method_opt=>'for all indexed columns',
                           cascade=>true );
 19      commit;
 20 end;
 21 /
Organization Counts
ops$tkyte%ORA11GR2> declare
  2      l_rec    heap%rowtype;
  3      cursor heap_cursor(p_username in varchar2) is
  4      select * from heap single_row where username = p_username;
  5      cursor iot_cursor(p_username in varchar2) is
  6      select * from iot single_row where username = p_username;
  7 begin
  8 for i in 1 .. 10
  9 loop
 10      for x in (select username from all_users) loop
 11          open heap_cursor(x.username);
 12          loop
 13               fetch heap_cursor into l_rec;
 14               exit when heap_cursor%notfound;
 15          end loop;
 16          close heap_cursor;
 17          open iot_cursor(x.username);
 18          loop
 19               fetch iot_cursor into l_rec;
 20               exit when iot_cursor%notfound;
 21          end loop;
 22          close iot_cursor;
 23      end loop;
 24 end loop;
 25 end;
 26 /
Organization Counts
   ops$tkyte%ORA11GR2> declare
     2      type array is table of iot%rowtype;
     3      l_data array;
     4 begin
     5 for i in 1 .. 10
     6 loop
     7      for x in (select username from all_users)
     8      loop
     9           select * bulk collect into l_data
    10             from heap bulk_collect
    11            where username = x.username;
    12           select * bulk collect into l_data
    13             from iot bulk_collect
    14            where username = x.username;
    15      end loop;
    16 end loop;
    17 end;
    18 /
   PL/SQL procedure successfully completed.
Organization Counts

SELECT * FROM HEAP SINGLE_ROW WHERE USERNAME = :B1

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute    410       0.02       0.02          0          0          0            0
Fetch    41410       0.25       0.27          0      82810          0        41000
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total    41821       0.28       0.30          0      82810          0        41000

Row Source Operation
---------------------------------------------------
TABLE ACCESS BY INDEX ROWID HEAP (cr=202 pr=0 pw=0 time=41 us cost=102 ...)
 INDEX RANGE SCAN HEAP_PK (cr=102 pr=0 pw=0 time=221 us cost=2 size=0 ca...)
Organization Counts

SELECT * FROM IOT SINGLE_ROW WHERE USERNAME = :B1

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute    410       0.02       0.02          0          0          0            0
Fetch    41410       0.16       0.18          0      42220          0        41000
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total    41821       0.19       0.21          0      42220          0        41000

Row Source Operation
---------------------------------------------------
INDEX RANGE SCAN IOT_PK (cr=103 pr=0 pw=0 time=33 us cost=21 size=102000 ...)
Organization Counts

SELECT * FROM HEAP BULK_COLLECT WHERE USERNAME = :B1

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute    410       0.01       0.02          0          0          0            0
Fetch      410       0.11       0.12          0      42010          0        41000
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total      821       0.13       0.14          0      42010          0        41000

Row Source Operation
---------------------------------------------------
TABLE ACCESS BY INDEX ROWID HEAP (cr=102 pr=0 pw=0 time=533 us cost=102 ...)
 INDEX RANGE SCAN HEAP_PK (cr=2 pr=0 pw=0 time=23 us cost=2 size=0 ca...)
Organization Counts

SELECT * FROM IOT BULK_COLLECT WHERE USERNAME = :B1

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute    410       0.01       0.02          0          0          0            0
Fetch      410       0.06       0.06          0       9000          0        41000
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total      821       0.08       0.08          0       9000          0        41000

Row Source Operation
---------------------------------------------------
INDEX RANGE SCAN IOT_PK (cr=22 pr=0 pw=0 time=142 us cost=21 size=102000...)
Knowing what is available

•  There is a lot out there…
•  I learn something new every day
•  Skimming the docs works
   –    Oh, I remember something similar…
•  Check out the “whats new in” at the head of the
   docs
•  Participate in the forums
•  Things change… Some things must be
   “discovered”
                                          Ignulls.sql
You have to learn new things…

ops$tkyte%ORA11GR2> select dt, val
  2    from t
  3   order by dt;

DT               VAL
--------- ----------
02-JAN-11        195
03-JAN-11
04-JAN-11
05-JAN-11
06-JAN-11        129
07-JAN-11
08-JAN-11
09-JAN-11
10-JAN-11         87
11-JAN-11

10 rows selected.
You have to learn new things…

ops$tkyte%ORA11GR2> select dt, val,
  2         case when val is not null
  3             then to_char(row_number() over (order by dt),'fm0000')||val
  4             end max_val
  5    from t
  6   order by dt;

DT               VAL MAX_VAL
--------- ---------- ---------------------------------------------
02-JAN-11        195 0001195
03-JAN-11
04-JAN-11
05-JAN-11
06-JAN-11        129 0005129
07-JAN-11
08-JAN-11
09-JAN-11
10-JAN-11         87 000987
11-JAN-11

10 rows selected.
You have to learn new things…
ops$tkyte%ORA11GR2> select dt, val,
  2         max(max_val) over (order by dt) max_val_str
  3    from ( select dt, val,
  4                  case when val is not null
  5                  then to_char(row_number() over (order by dt),'fm0000')||val
  6                   end max_val
  7    from t ) order by dt
  8 /

DT               VAL MAX_VAL_STR
--------- ---------- ---------------------------------------------
02-JAN-11        195 0001195
03-JAN-11            0001195
04-JAN-11            0001195
05-JAN-11            0001195
06-JAN-11        129 0005129
07-JAN-11            0005129
08-JAN-11            0005129
09-JAN-11            0005129
10-JAN-11         87 000987
11-JAN-11            000987

10 rows selected.
You have to learn new things…
ops$tkyte%ORA11GR2> select dt, val,
  2         to_number(substr(max(max_val) over (order by dt),5)) max_val
  3    from ( select dt, val,
  4                  case when val is not null
  5                  then to_char(row_number() over (order by dt),'fm0000')||val
  6                   end max_val
  7    from t ) order by dt
  8 /

DT               VAL    MAX_VAL
--------- ---------- ----------
02-JAN-11        195        195
03-JAN-11                   195
04-JAN-11                   195
05-JAN-11                   195
06-JAN-11        129        129
07-JAN-11                   129
08-JAN-11                   129
09-JAN-11                   129
10-JAN-11         87         87
11-JAN-11                    87

10 rows selected.
You have to learn new things…

ops$tkyte%ORA11GR2> select dt, val,
  2         last_value(val ignore nulls) over (order by dt) val
  3    from t
  4   order by dt
  5 /

DT               VAL        VAL
--------- ---------- ----------
02-JAN-11        195        195
03-JAN-11                   195
04-JAN-11                   195
05-JAN-11                   195
06-JAN-11        129        129
07-JAN-11                   129
08-JAN-11                   129
09-JAN-11                   129
10-JAN-11         87         87
11-JAN-11                    87

10 rows selected.
Things Change
 begin
      for x in
      ( select *
           from big_table.big_table
         where rownum <= 10000 )
      loop
           null;
      end loop;
 end;
Things Change
declare
     type array is table of big_table%rowtype;
     l_data array;
     cursor c is
            select * from big_table where rownum <= 1000;
begin
     open c;
     loop
          fetch c bulk collect into l_data limit 100;
          for i in 1 .. l_data.count
          loop
               null;
          end loop;
          exit when c%notfound;
     end loop;
     close c;
end;
Things Change 9i

SELECT * FROM BIG_TABLE.BIG_TABLE WHERE ROWNUM <= 10000

call     count        cpu    elapsed      query       rows
------- ------   -------- ---------- ---------- ----------
Parse        1       0.01       0.00          0          0
Execute      1       0.00       0.00          0          0
Fetch    10001       0.15       0.17      10005      10000
------- ------   -------- ---------- ---------- ----------
total    10003       0.16       0.17      10005      10000
Things Change 10g

SELECT * FROM BIG_TABLE.BIG_TABLE WHERE ROWNUM <= 10000

call     count        cpu    elapsed      query       rows
------- ------   -------- ---------- ---------- ----------
Parse        1       0.00       0.00          0          0
Execute      1       0.00       0.00          0          0
Fetch      101       0.05       0.07        152      10000
------- ------   -------- ---------- ---------- ----------
total      103       0.05       0.07        152      10000
Using ROWNUM

•  Psuedo Column – not a “real” column
•  Assigned after the predicate (sort of during) but
   before any sort/aggregation

Select x,y
  from t where rownum < 10
 order by x
Versus
Select * from
 (select x,y from t order by x)
 where rownum < 10
Using ROWNUM
•  Incremented after a successful output
Select * from t where rownum = 2

Rownum = 1
For x in ( select * from t )
Loop
   if ( rownum = 2 )
   then
      output record
      rownum = rownum+1;
   end if
End loop
Using ROWNUM
•  Top-N queries
Select *
   from (select * from t where … order by X )
  where rownum <= 10;

•    Does not have to sort the entire set
•    Sets up an “array” conceptually
•    Gets the first 10
•    When we get the 11th, see if it is in the top 10
       –    If so, push out an existing array element, slide this in
       –    Else throw it out and get the next one.
•  Do not attempt this in CODE! (well – what about 10g?)
                                                                       rn02.sql
Top-N
ops$tkyte%ORA11GR2> explain plan for
  2 select * from (select * from scott.emp order by sal desc) where rownum <= 10;

Explained.
ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
Plan hash value: 1744961472

--------------------------------------------------------------------------------
| Id | Operation                | Name | Rows | Bytes | Cost (%CPU)| Time      |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |    10 |   870 |     4 (25)| 00:00:01 |
|* 1 | COUNT STOPKEY            |      |       |       |            |          |
|   2 |   VIEW                  |      |    14 | 1218 |      4 (25)| 00:00:01 |
|* 3 |     SORT ORDER BY STOPKEY|      |    14 |   532 |     4 (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL   | EMP |     14 |   532 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter(ROWNUM<=10)
   3 - filter(ROWNUM<=10)

17 rows selected.
Top-N
    ops$tkyte%ORA11GR2> @mystat "sorts (disk)"
    NAME                        VALUE
    ---------------------- ----------
    sorts (disk)                    0

    ops$tkyte%ORA11GR2>   select *
      2    from (select   *
      3            from   big_table.big_table
      4           order   by object_id) where rownum <= 10;
    10 rows selected.

    Statistics
    ----------------------------------------------------------
     …         1 sorts (memory)
               0 sorts (disk)
             10 rows processed

    ops$tkyte%ORA11GR2> @mystat2
    NAME                         VALUE DIFF
    ---------------------- ---------- ------------------
    sorts (disk)                     0               0
Top-N
 ops$tkyte%ORA11GR2> @mystat "sorts (disk)"
 NAME                        VALUE
 ---------------------- ----------
 sorts (disk)                    0

 ops$tkyte%ORA11GR2> declare
   2     cursor c is
   3        select * from big_table.big_table order by object_id;
   4     l_rec big_table_v%rowtype;
   5 begin
   6     open c;
   7     for i in 1 .. 10
   8     loop
   9          fetch c into l_rec;
  10     end loop;
  11     close c;
  12 end;
  13 /
 PL/SQL procedure successfully completed.

 ops$tkyte%ORA11GR2> @mystat2
 NAME                         VALUE DIFF
 ---------------------- ---------- ------------------
 sorts (disk)                     1               1
Top-N

ops$tkyte%ORA11GR2> create index bt_idx on
                    big_table.big_table(object_id) ;

Index created.
Top-N
select *
  from (select *
          from big_table.big_table
         order by object_id) where rownum <= 10

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute      1       0.00       0.00          0          0          0            0
Fetch        2       0.00       0.00          2         14          0           10
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total        4       0.00       0.00          2         14          0           10

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 189
Number of plan statistics captured: 1

Row Source Operation
---------------------------------------------------
COUNT STOPKEY (cr=14 pr=2 pw=0 time=328 us)
  VIEW (cr=14 pr=2 pw=0 time=321 us cost=13 size=1410 card=10)
    TABLE ACCESS BY INDEX ROWID BIG_TABLE (cr=14 pr=2 pw=0 time=316 us …)
      INDEX FULL SCAN BT_IDX (cr=4 pr=2 pw=0 time=322 us cost=3 size=0 …)
Top-N

SELECT * FROM    BIG_TABLE.BIG_TABLE ORDER BY OBJECT_ID

call     count         cpu    elapsed       disk      query    current            rows
------- ------    -------- ---------- ---------- ---------- ----------      ----------
Parse        1        0.00       0.00          0          0          0               0
Execute      2        0.00       0.00          0          0          0               0
Fetch       10        1.12       2.17      14703      14544          7              10
------- ------    -------- ---------- ---------- ---------- ----------      ----------
total       13        1.12       2.17      14703      14544          7              10

Row Source Operation
---------------------------------------------------
SORT ORDER BY (cr=14544 pr=14703 pw=14639 time=2173284 us cost=26523 size...)
 TABLE ACCESS FULL BIG_TABLE (cr=14544 pr=14541 pw=0 time=694199 us cost=...)

Elapsed times include waiting on following events:
  Event waited on                             Times        Max. Wait   Total Waited
  ----------------------------------------   Waited       ----------   ------------
  direct path write temp                        476             0.00           1.23
  direct path read temp                            6            0.00           0.00
Using ROWNUM

•  Pagination

Select *
  From ( select      a.*, ROWNUM rnum
           From      ( your_query_goes_here ) a
          Where      ROWNUM <= :MAX_ROW_TO_FETCH )
 Where rnum >=       :MIN_ROW_TO_FETCH;

•  Everything from prior slide goes here…
•  Never ever let them “count the rows”, never.
•  Do not attempt this in CODE!
                                                  rn03.sql
Pagination

ops$tkyte%ORA11GR2>   set autotrace traceonly statistics
ops$tkyte%ORA11GR2>   variable max number
ops$tkyte%ORA11GR2>   variable min number
ops$tkyte%ORA11GR2>   exec :min := 100; :max := 115;

PL/SQL procedure successfully completed.
Pagination
select *
  from (select a.*, rownum rnum
          from (select /*+ FIRST_ROWS(15) */ *
                  from big_table.big_table order by object_id) a
         where rownum <= :Max)
 where rnum >= :min

call     count        cpu    elapsed       disk      query    current         rows
------- ------   -------- ---------- ---------- ---------- ----------   ----------
Parse        1       0.00       0.00          0          0          0            0
Execute      1       0.00       0.00          0          0          0            0
Fetch        3       0.00       0.00         12        119          0           16
------- ------   -------- ---------- ---------- ---------- ----------   ----------
total        5       0.00       0.00         12        119          0           16

Row Source Operation
---------------------------------------------------
VIEW (cr=119 pr=12 pw=0 time=939 us cost=18 size=2310 card=15)
 COUNT STOPKEY (cr=119 pr=12 pw=0 time=2840 us)
  VIEW (cr=119 pr=12 pw=0 time=2722 us cost=18 size=2115 card=15)
   TABLE ACCESS BY INDEX ROWID BIG_TABLE (cr=119 pr=12 pw=0 time=2605 us cost...)
    INDEX FULL SCAN BT_IDX (cr=4 pr=2 pw=0 time=258 us cost=3 size=0 card=...)
Pagination
ops$tkyte%ORA11GR2> declare
  2     cursor c is
  3        select * from big_table.big_table order by object_id;
  4     l_rec big_table_v%rowtype;
  5 begin
  6     open c;
  7     for i in 1 .. 115
  8     loop
  9          fetch c into l_rec;
 10          if ( i < 100 )
 11          then
 12               null;
 13          else
 14           null; -- process it
 15          end if;
 16     end loop;
 17     close c;
 18 end;
 19 /

PL/SQL procedure successfully completed.
Pagination

SELECT * FROM BIG_TABLE.BIG_TABLE ORDER BY OBJECT_ID

call     count        cpu    elapsed       disk      query    current          rows
------- ------   -------- ---------- ---------- ---------- ----------    ----------
Parse        1       0.00       0.00          0          0          0             0
Execute      2       0.00       0.00          0          0          0             0
Fetch      115       1.20       2.32      14703      14544          7           115
------- ------   -------- ---------- ---------- ---------- ----------    ----------
total      118       1.21       2.32      14703      14544          7           115

Row Source Operation
---------------------------------------------------
SORT ORDER BY (cr=14544 pr=14703 pw=14639 time=2324724 us cost=26523 size=...)
 TABLE ACCESS FULL BIG_TABLE (cr=14544 pr=14541 pw=0 time=682159 us cost=...)

Elapsed times include waiting on following events:
  Event waited on                             Times     Max. Wait   Total Waited
  ----------------------------------------   Waited    ----------   ------------
  direct path write temp                        571          0.00           1.34
  direct path read temp                            6         0.00           0.00
Scalar Subqueries

•  The ability to use a single column, single row query
   where you would normally use a “value”
Select dname, ‘Some Value’




From dept
•  That example shows a possible use of scalar
   subquerys – outer join removal
Scalar Subqueries

•  The ability to use a single column, single row query
   where you would normally use a “value”
Select dname, (select count(*)
                         from emp
                        where emp.deptno =
                               :dept.deptno ) cnt
From dept
•  That example shows a possible use of scalar
   subquerys – outer join removal
Scalar Subqueries

•  Outer join removal for “fast return” queries
    –    That works great for a single column
    –    What about when you need more than one?




                                                   ss01.sql
Scalar Subqueries
ops$tkyte%ORA11GR2> select *
  2    from (
  3 select a.owner, count(b.owner)
  4    from big_table.big_table_owners a left join big_table.big_table b
  5      on (a.owner = b.owner and b.object_type = 'TABLE' )
  6   group by a.owner
  7   order by a.owner
  8         )
  9   where rownum <= 2
 10 /

Statistics
----------------------------------------------------------
      14613 consistent gets
      14541 physical reads
           7 sorts (memory)
           0 sorts (disk)
           2 rows processed
Scalar Subqueries

ops$tkyte%ORA11GR2> select a.*,
  2         (select count(*)
  3             from big_table.big_table b
  4           where b.owner = a.owner and b.object_type = 'TABLE' ) cnt
  5    from (
  6 select a.owner
  7    from big_table.big_table_owners a
  8   order by a.owner
  9         ) a
 10   where rownum <= 2
 11 /

Statistics
----------------------------------------------------------
        590 consistent gets
           1 sorts (memory)
           0 sorts (disk)
           2 rows processed
Scalar Subqueries
ops$tkyte%ORA11GR2> select a.*,
  2         (select count(*)
  3             from big_table.big_table b
  4           where b.owner = a.owner and b.object_type = 'TABLE' ) cnt,
  5         (select min(created)
  6             from big_table.big_table b
  7           where b.owner = a.owner and b.object_type = 'TABLE' ) min_created,
  8         (select max(created)
  9             from big_table.big_table b
 10           where b.owner = a.owner and b.object_type = 'TABLE' ) max_created
 11    from (
 12 select a.owner
 13    from big_table.big_table_owners a
 14   order by a.owner
 15         ) a
 16   where rownum <= 2
 17 /

Statistics
----------------------------------------------------------
       1766 consistent gets
           1 sorts (memory)
           0 sorts (disk)
           2 rows processed
Scalar Subqueries
ops$tkyte%ORA11GR2> select owner,
  2          to_number(substr(data,1,10)) cnt,
  3          to_date(substr(data,11,14),'yyyymmddhh24miss') min_created,
  4          to_date(substr(data,25),'yyyymmddhh24miss') max_created
  5    from (
  6 select owner,
  7          (select to_char( count(*), 'fm0000000000') ||
  8                   to_char( min(created),'yyyymmddhh24miss') ||
  9                   to_char( max(created),'yyyymmddhh24miss')
 10              from big_table.big_table b
 11            where b.owner = a.owner and b.object_type = 'TABLE' ) data
 12    from (
 13 select a.owner
 14    from big_table.big_table_owners a
 15   order by a.owner
 16          ) a
 17   where rownum <= 2
 18          )
 19 /
Statistics
----------------------------------------------------------
        590 consistent gets
           1 sorts (memory)
           0 sorts (disk)
           2 rows processed
Scalar Subqueries

ops$tkyte%ORA11GR2> create or replace type myType as object
  2 ( cnt number, min_created date, max_created date )
  3 /

Type created.
Scalar Subqueries
ops$tkyte%ORA11GR2> select owner, a.data.cnt, a.data.min_created,
                            a.data.max_created
  2    from (
  3 select owner,
  4         (select myType( count(*), min(created), max(created) )
  5             from big_table.big_table b
  6           where b.owner = a.owner and b.object_type = 'TABLE' ) data
  7    from (
  8 select a.owner
  9    from big_table.big_table_owners a
 10   order by a.owner
 11         ) a
 12   where rownum <= 2
 13         ) a
 14 /

Statistics
----------------------------------------------------------
        590 consistent gets
           1 sorts (memory)
           0 sorts (disk)
           2 rows processed
Scalar Subqueries

•  Reducing PLSQL function calls via scalar subquery
   caching

Select * from t where x = pkg.getval()
versus
Select * from t where x =
     (select pkg.getval() from dual)

•  How to call them (scalar subqueries) “as little as
   possible”
                                             ss02.sql
Scalar Subqueries

ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number
  2 as
  3 begin
  4          dbms_application_info.set_client_info(userenv('client_info')+1 );
  5          return length(x);
  6 end;
  7 /

Function created.
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                          dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, f(owner) from stage;

72841 rows selected.

ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- ----------------------------------------------------------
       111 72841
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) f
                      from stage;

72841 rows selected.

ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- --------------------------------------------
        30 66
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) f
  2    from (select owner, rownum r from stage order by owner);

72841 rows selected.

ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- --------------------------------------------------------------
        32 32
Scalar Subqueries

ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number
  2 DETERMINISTIC
  3 as
  4 begin
  5          dbms_application_info.set_client_info(userenv('client_info')+1 );
  6          return length(x);
  7 end;
  8 /

Function created.
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, f(owner) from stage;

72841 rows selected.

ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- --------------------------------------------------------------
        73 8316
Scalar Subqueries

ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number
  2 RESULT_CACHE
  3 as
  4 begin
  5          dbms_application_info.set_client_info(userenv('client_info')+1 );
  6          return length(x);
  7 end;
  8 /

Function created.
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, f(owner) from stage;

72841 rows selected.

ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- ----------------------------------------------------------
        64 32
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, f(owner) from stage;
72841 rows selected.


ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs,
                           userenv('client_info') from dual;

 CPU_HSECS USERENV('CLIENT_INFO')
---------- -----------------------------------------------------------
        69 0
Scalar Subqueries

ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time;
                         dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) from stage;
72841 rows selected.


ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, user

 CPU_HSECS USERENV('CLIENT_INFO')
---------- --------------------------------------------------------------
        19 0
Don’t tune queries!
Think in SETS!
Questions

More Related Content

What's hot

12c SQL Plan Directives
12c SQL Plan Directives12c SQL Plan Directives
12c SQL Plan DirectivesFranck Pachot
 
Summary tables with flexviews
Summary tables with flexviewsSummary tables with flexviews
Summary tables with flexviewsJustin Swanhart
 
Oracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New FeaturesOracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New FeaturesAlex Zaballa
 
Oracle table lock modes
Oracle table lock modesOracle table lock modes
Oracle table lock modesFranck Pachot
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingSveta Smirnova
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain ExplainedJeremy Coates
 
Introduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]sIntroduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]sSveta Smirnova
 
Why Use EXPLAIN FORMAT=JSON?
 Why Use EXPLAIN FORMAT=JSON?  Why Use EXPLAIN FORMAT=JSON?
Why Use EXPLAIN FORMAT=JSON? Sveta Smirnova
 
Maximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestMaximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestPythian
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowAlex Zaballa
 
All on Adaptive and Extended Cursor Sharing
All on Adaptive and Extended Cursor SharingAll on Adaptive and Extended Cursor Sharing
All on Adaptive and Extended Cursor SharingMohamed Houri
 
Introduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]sIntroduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]sSveta Smirnova
 
New features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionNew features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionSveta Smirnova
 
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)Laurent Leturgez
 
Understanding Query Execution
Understanding Query ExecutionUnderstanding Query Execution
Understanding Query Executionwebhostingguy
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZENorvald Ryeng
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingSveta Smirnova
 
Introduction into MySQL Query Tuning
Introduction into MySQL Query TuningIntroduction into MySQL Query Tuning
Introduction into MySQL Query TuningSveta Smirnova
 
Basic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsBasic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsSveta Smirnova
 
エンタープライズ・クラウドと 並列・分散・非同期処理
エンタープライズ・クラウドと 並列・分散・非同期処理エンタープライズ・クラウドと 並列・分散・非同期処理
エンタープライズ・クラウドと 並列・分散・非同期処理maruyama097
 

What's hot (20)

12c SQL Plan Directives
12c SQL Plan Directives12c SQL Plan Directives
12c SQL Plan Directives
 
Summary tables with flexviews
Summary tables with flexviewsSummary tables with flexviews
Summary tables with flexviews
 
Oracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New FeaturesOracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New Features
 
Oracle table lock modes
Oracle table lock modesOracle table lock modes
Oracle table lock modes
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL Troubleshooting
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain Explained
 
Introduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]sIntroduction to MySQL Query Tuning for Dev[Op]s
Introduction to MySQL Query Tuning for Dev[Op]s
 
Why Use EXPLAIN FORMAT=JSON?
 Why Use EXPLAIN FORMAT=JSON?  Why Use EXPLAIN FORMAT=JSON?
Why Use EXPLAIN FORMAT=JSON?
 
Maximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestMaximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digest
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
 
All on Adaptive and Extended Cursor Sharing
All on Adaptive and Extended Cursor SharingAll on Adaptive and Extended Cursor Sharing
All on Adaptive and Extended Cursor Sharing
 
Introduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]sIntroduction into MySQL Query Tuning for Dev[Op]s
Introduction into MySQL Query Tuning for Dev[Op]s
 
New features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionNew features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in action
 
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)
Ukoug15 SIMD outside and inside Oracle 12c (12.1.0.2)
 
Understanding Query Execution
Understanding Query ExecutionUnderstanding Query Execution
Understanding Query Execution
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZE
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL Troubleshooting
 
Introduction into MySQL Query Tuning
Introduction into MySQL Query TuningIntroduction into MySQL Query Tuning
Introduction into MySQL Query Tuning
 
Basic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsBasic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database Administrators
 
エンタープライズ・クラウドと 並列・分散・非同期処理
エンタープライズ・クラウドと 並列・分散・非同期処理エンタープライズ・クラウドと 並列・分散・非同期処理
エンタープライズ・クラウドと 並列・分散・非同期処理
 

Viewers also liked

What Are We Still Doing Wrong
What Are We Still Doing WrongWhat Are We Still Doing Wrong
What Are We Still Doing Wrongafa reg
 
Eff Plsql
Eff PlsqlEff Plsql
Eff Plsqlafa reg
 
Oracle PL/SQL Bulk binds
Oracle PL/SQL Bulk bindsOracle PL/SQL Bulk binds
Oracle PL/SQL Bulk bindsScott Wesley
 
Common.logging
Common.loggingCommon.logging
Common.loggingLarry Nung
 
PL/SQL & SQL CODING GUIDELINES – Part 4
PL/SQL & SQL CODING GUIDELINES – Part 4PL/SQL & SQL CODING GUIDELINES – Part 4
PL/SQL & SQL CODING GUIDELINES – Part 4Larry Nung
 
Fx.configuration
Fx.configurationFx.configuration
Fx.configurationLarry Nung
 
Regular expression
Regular expressionRegular expression
Regular expressionLarry Nung
 
PL/SQL & SQL CODING GUIDELINES – Part 5
PL/SQL & SQL CODING GUIDELINES – Part 5PL/SQL & SQL CODING GUIDELINES – Part 5
PL/SQL & SQL CODING GUIDELINES – Part 5Larry Nung
 
Web deploy command line
Web deploy command lineWeb deploy command line
Web deploy command lineLarry Nung
 
Visual studio 2017
Visual studio 2017Visual studio 2017
Visual studio 2017Larry Nung
 
Advanced PL/SQL Optimizing for Better Performance 2016
Advanced PL/SQL Optimizing for Better Performance 2016Advanced PL/SQL Optimizing for Better Performance 2016
Advanced PL/SQL Optimizing for Better Performance 2016Zohar Elkayam
 
SonarQube - The leading platform for Continuous Code Quality
SonarQube - The leading platform for Continuous Code QualitySonarQube - The leading platform for Continuous Code Quality
SonarQube - The leading platform for Continuous Code QualityLarry Nung
 

Viewers also liked (14)

What Are We Still Doing Wrong
What Are We Still Doing WrongWhat Are We Still Doing Wrong
What Are We Still Doing Wrong
 
Eff Plsql
Eff PlsqlEff Plsql
Eff Plsql
 
Oracle PL/SQL Bulk binds
Oracle PL/SQL Bulk bindsOracle PL/SQL Bulk binds
Oracle PL/SQL Bulk binds
 
SikuliX
SikuliXSikuliX
SikuliX
 
Common.logging
Common.loggingCommon.logging
Common.logging
 
Web deploy
Web deployWeb deploy
Web deploy
 
PL/SQL & SQL CODING GUIDELINES – Part 4
PL/SQL & SQL CODING GUIDELINES – Part 4PL/SQL & SQL CODING GUIDELINES – Part 4
PL/SQL & SQL CODING GUIDELINES – Part 4
 
Fx.configuration
Fx.configurationFx.configuration
Fx.configuration
 
Regular expression
Regular expressionRegular expression
Regular expression
 
PL/SQL & SQL CODING GUIDELINES – Part 5
PL/SQL & SQL CODING GUIDELINES – Part 5PL/SQL & SQL CODING GUIDELINES – Part 5
PL/SQL & SQL CODING GUIDELINES – Part 5
 
Web deploy command line
Web deploy command lineWeb deploy command line
Web deploy command line
 
Visual studio 2017
Visual studio 2017Visual studio 2017
Visual studio 2017
 
Advanced PL/SQL Optimizing for Better Performance 2016
Advanced PL/SQL Optimizing for Better Performance 2016Advanced PL/SQL Optimizing for Better Performance 2016
Advanced PL/SQL Optimizing for Better Performance 2016
 
SonarQube - The leading platform for Continuous Code Quality
SonarQube - The leading platform for Continuous Code QualitySonarQube - The leading platform for Continuous Code Quality
SonarQube - The leading platform for Continuous Code Quality
 

Similar to Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf

APEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQLAPEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQLConnor McDonald
 
Query optimizer vivek sharma
Query optimizer vivek sharmaQuery optimizer vivek sharma
Query optimizer vivek sharmaaioughydchapter
 
Write Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfWrite Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfEric Xiao
 
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...InSync2011
 
Analyzing SQL Traces generated by EVENT 10046.pptx
Analyzing SQL Traces generated by EVENT 10046.pptxAnalyzing SQL Traces generated by EVENT 10046.pptx
Analyzing SQL Traces generated by EVENT 10046.pptxssuserbad8d3
 
Discard inport exchange table & tablespace
Discard inport exchange table & tablespaceDiscard inport exchange table & tablespace
Discard inport exchange table & tablespaceMarco Tusa
 
OTN tour 2015 AWR data mining
OTN tour 2015 AWR data miningOTN tour 2015 AWR data mining
OTN tour 2015 AWR data miningAndrejs Vorobjovs
 
Real World Performance - Data Warehouses
Real World Performance - Data WarehousesReal World Performance - Data Warehouses
Real World Performance - Data WarehousesConnor McDonald
 
AWR DB performance Data Mining - Collaborate 2015
AWR DB performance Data Mining - Collaborate 2015AWR DB performance Data Mining - Collaborate 2015
AWR DB performance Data Mining - Collaborate 2015Yury Velikanov
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeWim Godden
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeWim Godden
 
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...Kristofferson A
 
Oracle10g New Features I
Oracle10g New Features IOracle10g New Features I
Oracle10g New Features IDenish Patel
 
Oracle Database In-Memory Option in Action
Oracle Database In-Memory Option in ActionOracle Database In-Memory Option in Action
Oracle Database In-Memory Option in ActionTanel Poder
 
In Memory Database In Action by Tanel Poder and Kerry Osborne
In Memory Database In Action by Tanel Poder and Kerry OsborneIn Memory Database In Action by Tanel Poder and Kerry Osborne
In Memory Database In Action by Tanel Poder and Kerry OsborneEnkitec
 
zen and the art of SQL optimization
zen and the art of SQL optimizationzen and the art of SQL optimization
zen and the art of SQL optimizationKaren Morton
 
Top 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tipsTop 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tipsNirav Shah
 
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleUnderstanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleGuatemala User Group
 

Similar to Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf (20)

APEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQLAPEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQL
 
Query optimizer vivek sharma
Query optimizer vivek sharmaQuery optimizer vivek sharma
Query optimizer vivek sharma
 
Quick Wins
Quick WinsQuick Wins
Quick Wins
 
Write Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfWrite Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdf
 
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
 
Analyzing SQL Traces generated by EVENT 10046.pptx
Analyzing SQL Traces generated by EVENT 10046.pptxAnalyzing SQL Traces generated by EVENT 10046.pptx
Analyzing SQL Traces generated by EVENT 10046.pptx
 
Discard inport exchange table & tablespace
Discard inport exchange table & tablespaceDiscard inport exchange table & tablespace
Discard inport exchange table & tablespace
 
OTN tour 2015 AWR data mining
OTN tour 2015 AWR data miningOTN tour 2015 AWR data mining
OTN tour 2015 AWR data mining
 
Real World Performance - Data Warehouses
Real World Performance - Data WarehousesReal World Performance - Data Warehouses
Real World Performance - Data Warehouses
 
AWR DB performance Data Mining - Collaborate 2015
AWR DB performance Data Mining - Collaborate 2015AWR DB performance Data Mining - Collaborate 2015
AWR DB performance Data Mining - Collaborate 2015
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
 
SQLQueries
SQLQueriesSQLQueries
SQLQueries
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...
Hotsos 2011: Mining the AWR repository for Capacity Planning, Visualization, ...
 
Oracle10g New Features I
Oracle10g New Features IOracle10g New Features I
Oracle10g New Features I
 
Oracle Database In-Memory Option in Action
Oracle Database In-Memory Option in ActionOracle Database In-Memory Option in Action
Oracle Database In-Memory Option in Action
 
In Memory Database In Action by Tanel Poder and Kerry Osborne
In Memory Database In Action by Tanel Poder and Kerry OsborneIn Memory Database In Action by Tanel Poder and Kerry Osborne
In Memory Database In Action by Tanel Poder and Kerry Osborne
 
zen and the art of SQL optimization
zen and the art of SQL optimizationzen and the art of SQL optimization
zen and the art of SQL optimization
 
Top 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tipsTop 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tips
 
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleUnderstanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
 

More from InSync2011

Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...InSync2011
 
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdfNew & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdfInSync2011
 
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdfOracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdfInSync2011
 
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdfReporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdfInSync2011
 
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...InSync2011
 
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...InSync2011
 
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...InSync2011
 
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...InSync2011
 
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...InSync2011
 
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdfDatabase & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdfInSync2011
 
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...InSync2011
 
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...InSync2011
 
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...InSync2011
 
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...InSync2011
 
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...InSync2011
 
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...InSync2011
 
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...InSync2011
 
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...InSync2011
 
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...InSync2011
 
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...InSync2011
 

More from InSync2011 (20)

Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
 
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdfNew & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
 
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdfOracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
 
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdfReporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
 
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
 
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
 
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
 
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
 
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
 
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdfDatabase & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
 
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
 
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
 
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
 
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
 
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
 
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
 
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
 
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
 
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
 
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
 

Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf

  • 2. Who am I •  Been with Oracle since 1993 •  User of Oracle since 1987 •  The “Tom” behind AskTom in Oracle Magazine www.oracle.com/oramag •  Expert Oracle Database Architecture •  Effective Oracle by Design •  Expert One on One Oracle •  Beginning Oracle
  • 3. Agenda •  What do you need to write “good” SQL •  The Schema Matters •  Knowing what is available –  Using rownum (yes, to 'tune') –  Scalar subqueries –  Analytics –  Some hints •  Don’t tune queries! •  Other things –  Materialized Views –  With subquery factoring –  Merge –  …
  • 4. What do you need to know… •  Access Paths –  There are a lot of them –  There is no best one (else there would be, well, one) •  A little bit of physics –  Full scans are not evil –  Indexes are not all goodness •  How the data is managed by Oracle –  high water marks for example –  IOT’s, clusters, etc •  What your query needs to actually do –  Is that outer join really necessary or “just in case”
  • 5. Structures •  How the data is accessed and organized makes a difference –  Clustering Select * from orders o, line_items li ORDERS ORDERS & LINE where o.order# = li.order# LINE ITEMS ITEMS And o.order# = :order
  • 6. Structures •  How the data is accessed and organized makes a difference –  Clustering –  Index Organized Tables Select avg(price) STOCKS STOCKS From stocks Where symbol = ‘ORCL’ And stock_dt >= sysdate-5;
  • 7. Structures •  How the data is accessed and organized makes a difference –  Clustering –  Index Organized Tables ORDERS ORDERS ORDERS –  Partitioning Europe USA Jan Jan Feb Feb Composite Partition Partition Large Table Higher and Manage Divide Performance Difficult to Conquer More flexibility to match Easier to Manage business needs Improve Performance
  • 8. The Schema Matters •  A Lot! •  Tune this query: Select DOCUMENT_NAME, META_DATA from documents where userid=:x; •  That is about as easy as it gets (the SQL) •  Not too much we can do to rewrite it… •  But we’d like to make it better. Iot01.sql Cf.sql
  • 9. Organization Counts ops$tkyte%ORA11GR2> create table iot 2 ( username varchar2(30), 3 document_name varchar2(30), 4 other_data char(1000), 5 constraint iot_pk primary key (username,document_name)) 6 organization index 7 / Table created. ops$tkyte%ORA11GR2> create table heap 2 ( username varchar2(30), 3 document_name varchar2(30), 4 other_data char(1000), 5 constraint heap_pk primary key (username,document_name)) 6 / Table created.
  • 10. Organization Counts ops$tkyte%ORA11GR2> begin 2 for i in 1 .. 100 3 loop 4 for x in ( select username from all_users ) 5 loop 6 insert into heap 7 (username,document_name,other_data) values 8 ( x.username, x.username || '_' || i, 'x' ); 9 10 insert into iot 11 (username,document_name,other_data) values 12 ( x.username, x.username || '_' || i, 'x' ); 13 end loop; 14 end loop; 15 dbms_stats.gather_table_stats 16 ( user, 'IOT', cascade=>true ); 17 dbms_stats.gather_table_stats 18 ( user, 'HEAP', method_opt=>'for all indexed columns', cascade=>true ); 19 commit; 20 end; 21 /
  • 11. Organization Counts ops$tkyte%ORA11GR2> declare 2 l_rec heap%rowtype; 3 cursor heap_cursor(p_username in varchar2) is 4 select * from heap single_row where username = p_username; 5 cursor iot_cursor(p_username in varchar2) is 6 select * from iot single_row where username = p_username; 7 begin 8 for i in 1 .. 10 9 loop 10 for x in (select username from all_users) loop 11 open heap_cursor(x.username); 12 loop 13 fetch heap_cursor into l_rec; 14 exit when heap_cursor%notfound; 15 end loop; 16 close heap_cursor; 17 open iot_cursor(x.username); 18 loop 19 fetch iot_cursor into l_rec; 20 exit when iot_cursor%notfound; 21 end loop; 22 close iot_cursor; 23 end loop; 24 end loop; 25 end; 26 /
  • 12. Organization Counts ops$tkyte%ORA11GR2> declare 2 type array is table of iot%rowtype; 3 l_data array; 4 begin 5 for i in 1 .. 10 6 loop 7 for x in (select username from all_users) 8 loop 9 select * bulk collect into l_data 10 from heap bulk_collect 11 where username = x.username; 12 select * bulk collect into l_data 13 from iot bulk_collect 14 where username = x.username; 15 end loop; 16 end loop; 17 end; 18 / PL/SQL procedure successfully completed.
  • 13. Organization Counts SELECT * FROM HEAP SINGLE_ROW WHERE USERNAME = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 410 0.02 0.02 0 0 0 0 Fetch 41410 0.25 0.27 0 82810 0 41000 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 41821 0.28 0.30 0 82810 0 41000 Row Source Operation --------------------------------------------------- TABLE ACCESS BY INDEX ROWID HEAP (cr=202 pr=0 pw=0 time=41 us cost=102 ...) INDEX RANGE SCAN HEAP_PK (cr=102 pr=0 pw=0 time=221 us cost=2 size=0 ca...)
  • 14. Organization Counts SELECT * FROM IOT SINGLE_ROW WHERE USERNAME = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 410 0.02 0.02 0 0 0 0 Fetch 41410 0.16 0.18 0 42220 0 41000 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 41821 0.19 0.21 0 42220 0 41000 Row Source Operation --------------------------------------------------- INDEX RANGE SCAN IOT_PK (cr=103 pr=0 pw=0 time=33 us cost=21 size=102000 ...)
  • 15. Organization Counts SELECT * FROM HEAP BULK_COLLECT WHERE USERNAME = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 410 0.01 0.02 0 0 0 0 Fetch 410 0.11 0.12 0 42010 0 41000 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 821 0.13 0.14 0 42010 0 41000 Row Source Operation --------------------------------------------------- TABLE ACCESS BY INDEX ROWID HEAP (cr=102 pr=0 pw=0 time=533 us cost=102 ...) INDEX RANGE SCAN HEAP_PK (cr=2 pr=0 pw=0 time=23 us cost=2 size=0 ca...)
  • 16. Organization Counts SELECT * FROM IOT BULK_COLLECT WHERE USERNAME = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 410 0.01 0.02 0 0 0 0 Fetch 410 0.06 0.06 0 9000 0 41000 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 821 0.08 0.08 0 9000 0 41000 Row Source Operation --------------------------------------------------- INDEX RANGE SCAN IOT_PK (cr=22 pr=0 pw=0 time=142 us cost=21 size=102000...)
  • 17. Knowing what is available •  There is a lot out there… •  I learn something new every day •  Skimming the docs works –  Oh, I remember something similar… •  Check out the “whats new in” at the head of the docs •  Participate in the forums •  Things change… Some things must be “discovered” Ignulls.sql
  • 18. You have to learn new things… ops$tkyte%ORA11GR2> select dt, val 2 from t 3 order by dt; DT VAL --------- ---------- 02-JAN-11 195 03-JAN-11 04-JAN-11 05-JAN-11 06-JAN-11 129 07-JAN-11 08-JAN-11 09-JAN-11 10-JAN-11 87 11-JAN-11 10 rows selected.
  • 19. You have to learn new things… ops$tkyte%ORA11GR2> select dt, val, 2 case when val is not null 3 then to_char(row_number() over (order by dt),'fm0000')||val 4 end max_val 5 from t 6 order by dt; DT VAL MAX_VAL --------- ---------- --------------------------------------------- 02-JAN-11 195 0001195 03-JAN-11 04-JAN-11 05-JAN-11 06-JAN-11 129 0005129 07-JAN-11 08-JAN-11 09-JAN-11 10-JAN-11 87 000987 11-JAN-11 10 rows selected.
  • 20. You have to learn new things… ops$tkyte%ORA11GR2> select dt, val, 2 max(max_val) over (order by dt) max_val_str 3 from ( select dt, val, 4 case when val is not null 5 then to_char(row_number() over (order by dt),'fm0000')||val 6 end max_val 7 from t ) order by dt 8 / DT VAL MAX_VAL_STR --------- ---------- --------------------------------------------- 02-JAN-11 195 0001195 03-JAN-11 0001195 04-JAN-11 0001195 05-JAN-11 0001195 06-JAN-11 129 0005129 07-JAN-11 0005129 08-JAN-11 0005129 09-JAN-11 0005129 10-JAN-11 87 000987 11-JAN-11 000987 10 rows selected.
  • 21. You have to learn new things… ops$tkyte%ORA11GR2> select dt, val, 2 to_number(substr(max(max_val) over (order by dt),5)) max_val 3 from ( select dt, val, 4 case when val is not null 5 then to_char(row_number() over (order by dt),'fm0000')||val 6 end max_val 7 from t ) order by dt 8 / DT VAL MAX_VAL --------- ---------- ---------- 02-JAN-11 195 195 03-JAN-11 195 04-JAN-11 195 05-JAN-11 195 06-JAN-11 129 129 07-JAN-11 129 08-JAN-11 129 09-JAN-11 129 10-JAN-11 87 87 11-JAN-11 87 10 rows selected.
  • 22. You have to learn new things… ops$tkyte%ORA11GR2> select dt, val, 2 last_value(val ignore nulls) over (order by dt) val 3 from t 4 order by dt 5 / DT VAL VAL --------- ---------- ---------- 02-JAN-11 195 195 03-JAN-11 195 04-JAN-11 195 05-JAN-11 195 06-JAN-11 129 129 07-JAN-11 129 08-JAN-11 129 09-JAN-11 129 10-JAN-11 87 87 11-JAN-11 87 10 rows selected.
  • 23. Things Change begin for x in ( select * from big_table.big_table where rownum <= 10000 ) loop null; end loop; end;
  • 24. Things Change declare type array is table of big_table%rowtype; l_data array; cursor c is select * from big_table where rownum <= 1000; begin open c; loop fetch c bulk collect into l_data limit 100; for i in 1 .. l_data.count loop null; end loop; exit when c%notfound; end loop; close c; end;
  • 25. Things Change 9i SELECT * FROM BIG_TABLE.BIG_TABLE WHERE ROWNUM <= 10000 call count cpu elapsed query rows ------- ------ -------- ---------- ---------- ---------- Parse 1 0.01 0.00 0 0 Execute 1 0.00 0.00 0 0 Fetch 10001 0.15 0.17 10005 10000 ------- ------ -------- ---------- ---------- ---------- total 10003 0.16 0.17 10005 10000
  • 26. Things Change 10g SELECT * FROM BIG_TABLE.BIG_TABLE WHERE ROWNUM <= 10000 call count cpu elapsed query rows ------- ------ -------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 Execute 1 0.00 0.00 0 0 Fetch 101 0.05 0.07 152 10000 ------- ------ -------- ---------- ---------- ---------- total 103 0.05 0.07 152 10000
  • 27. Using ROWNUM •  Psuedo Column – not a “real” column •  Assigned after the predicate (sort of during) but before any sort/aggregation Select x,y from t where rownum < 10 order by x Versus Select * from (select x,y from t order by x) where rownum < 10
  • 28. Using ROWNUM •  Incremented after a successful output Select * from t where rownum = 2 Rownum = 1 For x in ( select * from t ) Loop if ( rownum = 2 ) then output record rownum = rownum+1; end if End loop
  • 29. Using ROWNUM •  Top-N queries Select * from (select * from t where … order by X ) where rownum <= 10; •  Does not have to sort the entire set •  Sets up an “array” conceptually •  Gets the first 10 •  When we get the 11th, see if it is in the top 10 –  If so, push out an existing array element, slide this in –  Else throw it out and get the next one. •  Do not attempt this in CODE! (well – what about 10g?) rn02.sql
  • 30. Top-N ops$tkyte%ORA11GR2> explain plan for 2 select * from (select * from scott.emp order by sal desc) where rownum <= 10; Explained. ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------- Plan hash value: 1744961472 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 870 | 4 (25)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | VIEW | | 14 | 1218 | 4 (25)| 00:00:01 | |* 3 | SORT ORDER BY STOPKEY| | 14 | 532 | 4 (25)| 00:00:01 | | 4 | TABLE ACCESS FULL | EMP | 14 | 532 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(ROWNUM<=10) 3 - filter(ROWNUM<=10) 17 rows selected.
  • 31. Top-N ops$tkyte%ORA11GR2> @mystat "sorts (disk)" NAME VALUE ---------------------- ---------- sorts (disk) 0 ops$tkyte%ORA11GR2> select * 2 from (select * 3 from big_table.big_table 4 order by object_id) where rownum <= 10; 10 rows selected. Statistics ---------------------------------------------------------- … 1 sorts (memory) 0 sorts (disk) 10 rows processed ops$tkyte%ORA11GR2> @mystat2 NAME VALUE DIFF ---------------------- ---------- ------------------ sorts (disk) 0 0
  • 32. Top-N ops$tkyte%ORA11GR2> @mystat "sorts (disk)" NAME VALUE ---------------------- ---------- sorts (disk) 0 ops$tkyte%ORA11GR2> declare 2 cursor c is 3 select * from big_table.big_table order by object_id; 4 l_rec big_table_v%rowtype; 5 begin 6 open c; 7 for i in 1 .. 10 8 loop 9 fetch c into l_rec; 10 end loop; 11 close c; 12 end; 13 / PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> @mystat2 NAME VALUE DIFF ---------------------- ---------- ------------------ sorts (disk) 1 1
  • 33. Top-N ops$tkyte%ORA11GR2> create index bt_idx on big_table.big_table(object_id) ; Index created.
  • 34. Top-N select * from (select * from big_table.big_table order by object_id) where rownum <= 10 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 2 14 0 10 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 4 0.00 0.00 2 14 0 10 Misses in library cache during parse: 1 Optimizer mode: ALL_ROWS Parsing user id: 189 Number of plan statistics captured: 1 Row Source Operation --------------------------------------------------- COUNT STOPKEY (cr=14 pr=2 pw=0 time=328 us) VIEW (cr=14 pr=2 pw=0 time=321 us cost=13 size=1410 card=10) TABLE ACCESS BY INDEX ROWID BIG_TABLE (cr=14 pr=2 pw=0 time=316 us …) INDEX FULL SCAN BT_IDX (cr=4 pr=2 pw=0 time=322 us cost=3 size=0 …)
  • 35. Top-N SELECT * FROM BIG_TABLE.BIG_TABLE ORDER BY OBJECT_ID call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 2 0.00 0.00 0 0 0 0 Fetch 10 1.12 2.17 14703 14544 7 10 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 13 1.12 2.17 14703 14544 7 10 Row Source Operation --------------------------------------------------- SORT ORDER BY (cr=14544 pr=14703 pw=14639 time=2173284 us cost=26523 size...) TABLE ACCESS FULL BIG_TABLE (cr=14544 pr=14541 pw=0 time=694199 us cost=...) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ direct path write temp 476 0.00 1.23 direct path read temp 6 0.00 0.00
  • 36. Using ROWNUM •  Pagination Select * From ( select a.*, ROWNUM rnum From ( your_query_goes_here ) a Where ROWNUM <= :MAX_ROW_TO_FETCH ) Where rnum >= :MIN_ROW_TO_FETCH; •  Everything from prior slide goes here… •  Never ever let them “count the rows”, never. •  Do not attempt this in CODE! rn03.sql
  • 37. Pagination ops$tkyte%ORA11GR2> set autotrace traceonly statistics ops$tkyte%ORA11GR2> variable max number ops$tkyte%ORA11GR2> variable min number ops$tkyte%ORA11GR2> exec :min := 100; :max := 115; PL/SQL procedure successfully completed.
  • 38. Pagination select * from (select a.*, rownum rnum from (select /*+ FIRST_ROWS(15) */ * from big_table.big_table order by object_id) a where rownum <= :Max) where rnum >= :min call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 3 0.00 0.00 12 119 0 16 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 5 0.00 0.00 12 119 0 16 Row Source Operation --------------------------------------------------- VIEW (cr=119 pr=12 pw=0 time=939 us cost=18 size=2310 card=15) COUNT STOPKEY (cr=119 pr=12 pw=0 time=2840 us) VIEW (cr=119 pr=12 pw=0 time=2722 us cost=18 size=2115 card=15) TABLE ACCESS BY INDEX ROWID BIG_TABLE (cr=119 pr=12 pw=0 time=2605 us cost...) INDEX FULL SCAN BT_IDX (cr=4 pr=2 pw=0 time=258 us cost=3 size=0 card=...)
  • 39. Pagination ops$tkyte%ORA11GR2> declare 2 cursor c is 3 select * from big_table.big_table order by object_id; 4 l_rec big_table_v%rowtype; 5 begin 6 open c; 7 for i in 1 .. 115 8 loop 9 fetch c into l_rec; 10 if ( i < 100 ) 11 then 12 null; 13 else 14 null; -- process it 15 end if; 16 end loop; 17 close c; 18 end; 19 / PL/SQL procedure successfully completed.
  • 40. Pagination SELECT * FROM BIG_TABLE.BIG_TABLE ORDER BY OBJECT_ID call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 2 0.00 0.00 0 0 0 0 Fetch 115 1.20 2.32 14703 14544 7 115 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 118 1.21 2.32 14703 14544 7 115 Row Source Operation --------------------------------------------------- SORT ORDER BY (cr=14544 pr=14703 pw=14639 time=2324724 us cost=26523 size=...) TABLE ACCESS FULL BIG_TABLE (cr=14544 pr=14541 pw=0 time=682159 us cost=...) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ direct path write temp 571 0.00 1.34 direct path read temp 6 0.00 0.00
  • 41. Scalar Subqueries •  The ability to use a single column, single row query where you would normally use a “value” Select dname, ‘Some Value’ From dept •  That example shows a possible use of scalar subquerys – outer join removal
  • 42. Scalar Subqueries •  The ability to use a single column, single row query where you would normally use a “value” Select dname, (select count(*) from emp where emp.deptno = :dept.deptno ) cnt From dept •  That example shows a possible use of scalar subquerys – outer join removal
  • 43. Scalar Subqueries •  Outer join removal for “fast return” queries –  That works great for a single column –  What about when you need more than one? ss01.sql
  • 44. Scalar Subqueries ops$tkyte%ORA11GR2> select * 2 from ( 3 select a.owner, count(b.owner) 4 from big_table.big_table_owners a left join big_table.big_table b 5 on (a.owner = b.owner and b.object_type = 'TABLE' ) 6 group by a.owner 7 order by a.owner 8 ) 9 where rownum <= 2 10 / Statistics ---------------------------------------------------------- 14613 consistent gets 14541 physical reads 7 sorts (memory) 0 sorts (disk) 2 rows processed
  • 45. Scalar Subqueries ops$tkyte%ORA11GR2> select a.*, 2 (select count(*) 3 from big_table.big_table b 4 where b.owner = a.owner and b.object_type = 'TABLE' ) cnt 5 from ( 6 select a.owner 7 from big_table.big_table_owners a 8 order by a.owner 9 ) a 10 where rownum <= 2 11 / Statistics ---------------------------------------------------------- 590 consistent gets 1 sorts (memory) 0 sorts (disk) 2 rows processed
  • 46. Scalar Subqueries ops$tkyte%ORA11GR2> select a.*, 2 (select count(*) 3 from big_table.big_table b 4 where b.owner = a.owner and b.object_type = 'TABLE' ) cnt, 5 (select min(created) 6 from big_table.big_table b 7 where b.owner = a.owner and b.object_type = 'TABLE' ) min_created, 8 (select max(created) 9 from big_table.big_table b 10 where b.owner = a.owner and b.object_type = 'TABLE' ) max_created 11 from ( 12 select a.owner 13 from big_table.big_table_owners a 14 order by a.owner 15 ) a 16 where rownum <= 2 17 / Statistics ---------------------------------------------------------- 1766 consistent gets 1 sorts (memory) 0 sorts (disk) 2 rows processed
  • 47. Scalar Subqueries ops$tkyte%ORA11GR2> select owner, 2 to_number(substr(data,1,10)) cnt, 3 to_date(substr(data,11,14),'yyyymmddhh24miss') min_created, 4 to_date(substr(data,25),'yyyymmddhh24miss') max_created 5 from ( 6 select owner, 7 (select to_char( count(*), 'fm0000000000') || 8 to_char( min(created),'yyyymmddhh24miss') || 9 to_char( max(created),'yyyymmddhh24miss') 10 from big_table.big_table b 11 where b.owner = a.owner and b.object_type = 'TABLE' ) data 12 from ( 13 select a.owner 14 from big_table.big_table_owners a 15 order by a.owner 16 ) a 17 where rownum <= 2 18 ) 19 / Statistics ---------------------------------------------------------- 590 consistent gets 1 sorts (memory) 0 sorts (disk) 2 rows processed
  • 48. Scalar Subqueries ops$tkyte%ORA11GR2> create or replace type myType as object 2 ( cnt number, min_created date, max_created date ) 3 / Type created.
  • 49. Scalar Subqueries ops$tkyte%ORA11GR2> select owner, a.data.cnt, a.data.min_created, a.data.max_created 2 from ( 3 select owner, 4 (select myType( count(*), min(created), max(created) ) 5 from big_table.big_table b 6 where b.owner = a.owner and b.object_type = 'TABLE' ) data 7 from ( 8 select a.owner 9 from big_table.big_table_owners a 10 order by a.owner 11 ) a 12 where rownum <= 2 13 ) a 14 / Statistics ---------------------------------------------------------- 590 consistent gets 1 sorts (memory) 0 sorts (disk) 2 rows processed
  • 50. Scalar Subqueries •  Reducing PLSQL function calls via scalar subquery caching Select * from t where x = pkg.getval() versus Select * from t where x = (select pkg.getval() from dual) •  How to call them (scalar subqueries) “as little as possible” ss02.sql
  • 51. Scalar Subqueries ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number 2 as 3 begin 4 dbms_application_info.set_client_info(userenv('client_info')+1 ); 5 return length(x); 6 end; 7 / Function created.
  • 52. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, f(owner) from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- ---------------------------------------------------------- 111 72841
  • 53. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) f from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- -------------------------------------------- 30 66
  • 54. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) f 2 from (select owner, rownum r from stage order by owner); 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- -------------------------------------------------------------- 32 32
  • 55. Scalar Subqueries ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number 2 DETERMINISTIC 3 as 4 begin 5 dbms_application_info.set_client_info(userenv('client_info')+1 ); 6 return length(x); 7 end; 8 / Function created.
  • 56. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, f(owner) from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- -------------------------------------------------------------- 73 8316
  • 57. Scalar Subqueries ops$tkyte%ORA11GR2> create or replace function f( x in varchar2 ) return number 2 RESULT_CACHE 3 as 4 begin 5 dbms_application_info.set_client_info(userenv('client_info')+1 ); 6 return length(x); 7 end; 8 / Function created.
  • 58. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, f(owner) from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- ---------------------------------------------------------- 64 32
  • 59. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, f(owner) from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, userenv('client_info') from dual; CPU_HSECS USERENV('CLIENT_INFO') ---------- ----------------------------------------------------------- 69 0
  • 60. Scalar Subqueries ops$tkyte%ORA11GR2> exec :cpu := dbms_utility.get_cpu_time; dbms_application_info.set_client_info(0); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select owner, (select f(owner) from dual) from stage; 72841 rows selected. ops$tkyte%ORA11GR2> select dbms_utility.get_cpu_time-:cpu cpu_hsecs, user CPU_HSECS USERENV('CLIENT_INFO') ---------- -------------------------------------------------------------- 19 0