Você está na página 1de 270

Oracle Tuning: SQL

Ricardo Portilho Proni


ricardo@nervinformatica.com.br
Esta obra est licenciada sob a licena
Creative Commons Atribuio-SemDerivados 3.0 Brasil.
Para ver uma cpia desta licena, visite
http://creativecommons.org/licenses/by-nd/3.0/br/.

Dicas de SQL Tuning?

Lendas de SQL
O Custo no quer dizer nada?
ndice BITMAP em baixa cardinalidade?

Sintaxe Oracle ou ANSI?

SELECT(1) ou SELECT COUNT(*)?

Ordem da clusula WHERE?

Ordem de JOIN?

CHAR ou VARCHAR2?

Evite Subqueries?

Evite VIEWs?

Evite EXISTS?

Evite Listas IN?

NESTED LOOPs ruim?

< > melhor que BETWEEN?

Lab 1 Lendas de SQL


Hands On !

Lab 1.1: Lendas de SQL - COUNT(*)


Desbloqueie os usurios teste do Oracle Database, e d as permisses abaixo.
$ sqlplus / AS SYSDBA
SQL> ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED BY TIGER;
SQL> ALTER USER HR ACCOUNT UNLOCK IDENTIFIED BY HR;
SQL> ALTER USER SH ACCOUNT UNLOCK IDENTIFIED BY SH;
SQL> ALTER USER SHSB ACCOUNT UNLOCK IDENTIFIED BY SHSB;
SQL> ALTER USER SHSBP ACCOUNT UNLOCK IDENTIFIED BY SHSBP;
SQL> ALTER USER OE ACCOUNT UNLOCK IDENTIFIED BY OE;
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY
SQL> GRANT ALTER SESSION, RESOURCE, SELECT ANY DICTIONARY

TO
TO
TO
TO
TO
TO
TO

SCOTT;
HR;
SH;
SHSB;
SHSBP;
OE;
SOE;

Lab 1.2: Lendas de SQL - COUNT(*)


Execute logon com o usurio SCOTT, e verifique qual seu arquivo de TRACE:
$ sqlplus SCOTT/TIGER
SQL> COLUMN TRACEFILE FORMAT A100
SQL> SELECT P.TRACEFILE FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';

Coloque sua sesso em TRACE 10053, e execute os comandos abaixo.


SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SELECT COUNT(EMPNO) FROM EMP;
SELECT COUNT(1) FROM EMP;
SELECT COUNT(2) FROM EMP;
SELECT COUNT(*) FROM EMP;
SELECT COUNT(ROWID) FROM EMP;
SELECT COUNT(MGR) FROM EMP;

Edite o seu arquivo de TRACE.

$ vi /u01/app/oracle/rdbms/ORCL/orcl/trace/ORCL_ora_1234.trc

Lab 1.3: Lendas de SQL - COUNT(*)


No arquivo de Trace, procure pelo texto CNT:
Legend
The following abbreviations are used by optimizer trace.
CBQT - cost-based query transformation
JPPD - join predicate push-down
OJPPD - old-style (non-cost-based) JPPD
FPD - filter push-down
PM - predicate move-around
CVM - complex view merging
SPJ - select-project-join
SJC - set join conversion
SU - subquery unnesting
OBYE - order by elimination
OST - old style star transformation
ST - new (cbqt) star transformation
CNT - count(col) to count(*) transformation
JE - Join Elimination
JF - join factorization

Lab 1.4: Lendas de SQL - COUNT(*)


Procure novamente pelo texto CNT:

CNT:
Considering count(col) to count(*) on query block SEL$1 (#0)
*************************
Count(col) to Count(*) (CNT)
*************************
CNT:
Converting COUNT(EMPNO) to COUNT(*).
CNT:
COUNT() to COUNT(*) done.

Procure pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT COUNT(*) "COUNT(EMPNO)" FROM "SCOTT"."EMP" "EMP"

Lab 1.5: Lendas de SQL - COUNT(*)


Procure novamente pelo texto CNT:

CNT:
Considering count(col) to count(*) on query block SEL$1 (#0)
*************************
Count(col) to Count(*) (CNT)
*************************
CNT:
COUNT() to COUNT(*) done.

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT COUNT(*) "COUNT(1)" FROM "SCOTT"."EMP" "EMP"

Lab 1.6: Lendas de SQL - COUNT(*)


Procure novamente pelo texto CNT:

CNT:
Considering count(col) to count(*) on query block SEL$1 (#0)
*************************
Count(col) to Count(*) (CNT)
*************************
CNT:
COUNT() to COUNT(*) done.

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT COUNT(*) "COUNT(2)" FROM "SCOTT"."EMP" "EMP"

10

Lab 1.7: Lendas de SQL - COUNT(*)


Procure novamente pelo texto CNT:

CNT:
Considering count(col) to count(*) on query block SEL$1 (#0)
*************************
Count(col) to Count(*) (CNT)
*************************
CNT:
COUNT() to COUNT(*) not done.

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT COUNT(*) "COUNT(*)" FROM "SCOTT"."EMP" "EMP"

11

Lab 1.8: Lendas de SQL - COUNT(*)


Procure novamente pelo texto CNT:
CN T: Considering count(col) to count(*) on query block SEL$1 (# 0)
*************************
Count(col) to Count(*) (CN T)
*************************
CN T: CO U N T() to CO U N T(*) not done.

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT COUNT("EMP".ROWID) "COUNT(ROWID)" FROM "SCOTT"."EMP" "EMP"

12

Lab 1.9: Lendas de SQL - ANSI


Execute os comandos abaixo.
SQL> SELECT
FROM
SQL> SELECT
FROM

E.ENAME, E.JOB, D.DNAME


EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO;
E.ENAME, E.JOB, D.DNAME
EMP E INNER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT "E"."ENAME" "ENAME","E"."JOB" "JOB","D"."DNAME" "DNAME" FROM
"SCOTT"."EMP" "E","SCOTT"."DEPT" "D" WHERE "E"."DEPTNO"="D"."DEPTNO"

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT "E"."ENAME" "ENAME","E"."JOB" "JOB","D"."DNAME" "DNAME" FROM
"SCOTT"."EMP" "E","SCOTT"."DEPT" "D" WHERE "E"."DEPTNO"="D"."DEPTNO"

13

Lab 1.10: Lendas de SQL- Listas IN


Execute os comandos abaixo.
SQL> SELECT E.ENAME, E.JOB, D.DNAME FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND EMPNO IN (7369,7499,7521,7566,7654);

Procure novamente pelo texto Final query:

Final query after transformations:******* UNPARSED QUERY IS *******


SELECT "E"."ENAME" "ENAME","E"."JOB" "JOB","D"."DNAME" "DNAME" FROM
"SCOTT"."EMP" "E","SCOTT"."DEPT" "D" WHERE "E"."DEPTNO"="D"."DEPTNO" AND
("E"."EMPNO"=7369 OR "E"."EMPNO"=7499 OR "E"."EMPNO"=7521 OR
"E"."EMPNO"=7566 OR "E"."EMPNO"=7654)

14

Top Ten Mistakes


1 - Bad connection management
2 - Bad use of cursors and the shared pool
3 - Bad SQL
4 - Use of nonstandard initialization parameters
5 - Getting database I/O wrong
6 - Online redo log setup problems
7 - Serialization of data blocks in the buffer cache due to lack of free lists, free list groups,
transaction slots (INITRANS), or shortage of rollback segments.
8 - Long full table scans
9 - High amounts of recursive (SYS) SQL
10 - Deployment and migration errors

Fonte: Oracle Database Performance Tuning Guide


http://docs.oracle.com/database/121/TGDBA/pfgrf_technique.htm#TGDBA032

15

15

SQL ou PL/SQL?
Se voc pode fazer algo em SQL, faa-o em SQL.
Se voc no pode faze-lo em SQL, faa em PL/SQL.
Se voc no pode faze-lo em PL/SQL, faa em Java.
Se voc no pode faze-lo em Java, faa em C++.
Se voc no pode fazer em C++, no o faa.
Thomas Kyte

- O que voc aprendeu sobre carros, quando aprendeu a dirigir?


- Quanto tempo voc levou para aprender SQL?
- Utilizamos apenas cerca de 20% das capacidades de um programa ou linguagem.

16

16

Contedo
Iremos abordar:
- SQL
No iremos:
- PL/SQL
- Analytic / OLAP / Data Mining
- LOB / SecureFiles
- XML
- HTML DB / APEX
- Oracle Text
- Oracle Spatial
- Intermedia / Image
- JDBC / OCI
- ODBC / ADO / .NET

17

17

Agenda
- Lendas de SQL
- Custo
- Configurao do CBO
- Seletividade e Cardinalidade
- SQL Engine
- Access Paths
- Query Transformation
- Join Methods
- ndices
- Anlise de Estatsticas
- Coleta de Estatsticas
- Modelagem / Data Types
- Extrao de Planos de Execuo
- Anlise de Planos de Execuo
- Estabilidade de Plano de Execuo
- Ferramentas (Trace 10046, Trace 10053, SQLHC, SQLT)
- Otimizaes (Paralelismo / CTAS / External Tables / Compresso / InMemory)
- Melhores Prticas em SQL

18

18

Cost Based Optimizer

19

SQL Tuning Guide

20

20

Oracle Optimizer Blog

21

21

Cost Based Optimizer


Exite uma teoria de que se algum descobrir o que o CBO faz e como ele funciona,
ele ir desaparecer instantaneamente e ser substitudo por algo ainda mais bizarro e
inexplicvel.
Existe outra teoria de que isto j aconteceu... duas vezes.
Jonathan Lewis, parafraseando Douglas Adams.

22

22

O que o Custo?
Execution Plan
-------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
14 |
84 |
3
(0)| 00:00:01 |
|
1 | TABLE ACCESS FULL| EMP |
14 |
84 |
3
(0)| 00:00:01 |
--------------------------------------------------------------------------

Cost = (
#SRds * sreadtim +
#MRds * mreadtim +
#CPUCycles / cpuspeed
) / sreadtim
OU
Custo = (
Quantidade de leituras de um nico bloco * Tempo de leitura de um nico bloco +
Quantidade de leituras de mltiplos blocos * Tempo de leitura de mltiplos blocos +
Ciclos de CPU / Velocidade da CPU
) / Tempo de leitura de um nico bloco

23

O que o Custo?

24

O que o Custo?

25

Seletividade e Cardinalidade
Seletividade
um valor entre 0 e 1 que representa a frao de linhas obtidas por uma operao.
Cardinalidade
o nmero de linhas retornadas por uma operao.
Exemplo:
SQL> SELECT COUNT(MODELS) FROM CARS;
120 rows selected.
SQL> SELECT COUNT(MODELS) FROM CARS WHERE FAB = 'FORD';
18 rows selected.
Cardinalidade = 18.
Seletividade = 0.15 (18/120).

26

Configurao do CBO
OPTIMIZER_MODE (FIRST_ROWS_n / ALL_ROWS)
DB_FILE_MULTIBLOCK_READ_COUNT

RESULT_CACHE

INMEMORY

OPTIMIZER_SECURE_VIEW_MERGING
QUERY_REWRITE_ENABLED

QUERY_REWRITE_INTEGRITY

STAR_TRANSFORMATION_ENABLED

GATHER_SYSTEM_STATISTICS
GATHER_DATABASE_STATISTICS

OPTIMIZER_DYNAMIC_SAMPLING

WORKAREA_SIZE_POLICY (AUTO / MANUAL)


AUTO:
PGA_AGGREGATE_TARGET

MANUAL:
BITMAP_MERGE_AREA_SIZE
HASH_AREA_SIZE
SORT_AREA_SIZE
SORT_AREA_RETAINED_SIZE

OPTIMIZER_INDEX_CACHING (0 a 100, padro 0)


OPTIMIZER_INDEX_COST_ADJ (1 a 10000, padro 100)

Histograms

Extended Statistics

27

Configurao do CBO - OLTP


OPTIMIZER_MODE (FIRST_ROWS_n / ALL_ROWS)
< DB_FILE_MULTIBLOCK_READ_COUNT

RESULT_CACHE

INMEMORY

OPTIMIZER_SECURE_VIEW_MERGING
QUERY_REWRITE_ENABLED

QUERY_REWRITE_INTEGRITY

STAR_TRANSFORMATION_ENABLED

GATHER_SYSTEM_STATISTICS
GATHER_DATABASE_STATISTICS

OPTIMIZER_DYNAMIC_SAMPLING

WORKAREA_SIZE_POLICY (AUTO / MANUAL)


AUTO:
PGA_AGGREGATE_TARGET

MANUAL:
BITMAP_MERGE_AREA_SIZE
HASH_AREA_SIZE
SORT_AREA_SIZE
SORT_AREA_RETAINED_SIZE

> OPTIMIZER_INDEX_CACHING
< OPTIMIZER_INDEX_COST_ADJ

Histograms

Extended Statistics

28

Configurao do CBO - OLAP


OPTIMIZER_MODE (FIRST_ROWS_n / ALL_ROWS)
> DB_FILE_MULTIBLOCK_READ_COUNT

RESULT_CACHE

INMEMORY

OPTIMIZER_SECURE_VIEW_MERGING
QUERY_REWRITE_ENABLED

QUERY_REWRITE_INTEGRITY

STAR_TRANSFORMATION_ENABLED

GATHER_SYSTEM_STATISTICS
GATHER_DATABASE_STATISTICS

OPTIMIZER_DYNAMIC_SAMPLING

WORKAREA_SIZE_POLICY (AUTO / MANUAL)


AUTO:
PGA_AGGREGATE_TARGET

MANUAL:
BITMAP_MERGE_AREA_SIZE
HASH_AREA_SIZE
SORT_AREA_SIZE
SORT_AREA_RETAINED_SIZE

< OPTIMIZER_INDEX_CACHING
> OPTIMIZER_INDEX_COST_ADJ

Histograms

Extended Statistics

29

Ferramentas Bsicas

30

AUTOTRACE
SQL> SET AUTOTRACE ON;
SQL> SELECT ENAME FROM EMP;
ENAME
---------SMITH
...
14 rows selected.
Execution Plan
---------------------------------------------------------Plan hash value: 3956160932
-------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
14 |
84 |
3
(0)| 00:00:01 |
|
1 | TABLE ACCESS FULL| EMP |
14 |
84 |
3
(0)| 00:00:01 |
-------------------------------------------------------------------------Statistics
---------------------------------------------------------1 recursive calls
...
0 sorts (disk)
14 rows processed

31

AUTOTRACE
SQL> SET AUTOTRACE TRACEONLY;
SQL> SELECT ENAME FROM EMP;
14 rows selected.
Execution Plan
---------------------------------------------------------Plan hash value: 3956160932
-------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
14 |
84 |
3
(0)| 00:00:01 |
|
1 | TABLE ACCESS FULL| EMP |
14 |
84 |
3
(0)| 00:00:01 |
-------------------------------------------------------------------------Statistics
---------------------------------------------------------0 recursive calls
0 db block gets
...
0 sorts (disk)
14 rows processed

32

AUTOTRACE
SQL> SET AUTOTRACE TRACEONLY EXPLAIN;
SQL> SELECT ENAME FROM EMP;
Execution Plan
---------------------------------------------------------Plan hash value: 3956160932
-------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
14 |
84 |
3
(0)| 00:00:01 |
|
1 | TABLE ACCESS FULL| EMP |
14 |
84 |
3
(0)| 00:00:01 |
-------------------------------------------------------------------------SQL>

33

AUTOTRACE
SQL> SET AUTOTRACE TRACEONLY STATISTICS;
SQL> SELECT ENAME FROM EMP;
14 rows selected.
Statistics
---------------------------------------------------------0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
731 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
14 rows processed
SQL>

34

SQL Developer: Plano de Execuo

35

SQL Developer: Plano de Execuo

36

SQL Trace (Event 10046): Nveis


0 - Trace OFF
2 - Regular SQL Trace
4 - Nvel 2, + Bind Variable
8 - Nvel 2 + Wait Events
12 - Nvel 2, + Bind Variable + Wait Events

37

SQL Trace (Event 10046): Ativao


Todas verses:
SQL> ALTER SESSION SET SQL_TRACE=TRUE;
SQL> ALTER SESSION SET SQL_TRACE=FALSE;
SQL> EXEC DBMS_SESSION.SET_SQL_TRACE(SQL_TRACE => TRUE);
SQL> EXEC DBMS_SESSION.SET_SQL_TRACE(SQL_TRACE => FALSE);
SQL> EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION
(SID=>123, SERIAL#=>1234, SQL_TRACE=>TRUE);
SQL> EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION
(SID=>123, SERIAL#=>1234, SQL_TRACE=>FALSE);
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';
SQL> EXEC DBMS_SYSTEM.SET_EV(SI=>123, SE=>1234, EV=>10046, LE=>12, NM=>'');
SQL> EXEC DBMS_SYSTEM.SET_EV(SI=>123, SE=>1234, EV=>10046, LE=>0, NM=>'');

38

SQL Trace (Event 10046): Ativao


Verses >= 8I
SQL> SELECT P.SPID OS_PROCESS_ID
FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';
SQL> ORADEBUG SETOSPID 12345;
SQL> ORADEBUG EVENT 10046 TRACE NAME CONTEXT FOREVER, LEVEL 12;
SQL> ORADEBUG TRACEFILE_NAME;
SQL> ORADEBUG EVENT 10046 TRACE NAME CONTEXT OFF;

39

SQL Trace (Event 10046): Ativao


CREATE OR REPLACE TRIGGER SET_TRACE AFTER LOGON ON DATABASE
BEGIN
IF USER IN ('SCOTT') THEN
EXECUTE IMMEDIATE
'ALTER SESSION SET TRACEFILE_IDENTIFIER=''SESSAO_RASTREADA_PORTILHO''';
EXECUTE IMMEDIATE
'ALTER SESSION SET TIMED_STATISTICS=TRUE';
EXECUTE IMMEDIATE
'ALTER SESSION SET MAX_DUMP_FILE_SIZE=UNLIMITED';
EXECUTE IMMEDIATE
'ALTER SESSION SET EVENTS ''10046 TRACE NAME CONTEXT FOREVER, LEVEL 12''';
END IF;
END;
/

40

SQL Trace (Event 10046): Ativao


Todas verses:
SQL> EXEC DBMS_SUPPORT.START_TRACE(WAITS=>TRUE, BINDS=>FALSE);
SQL> EXEC DBMS_SUPPORT.STOP_TRACE;
SQL> EXEC DBMS_SUPPORT.START_TRACE_IN_SESSION
(SID=>123, SERIAL=>1234, WAITS=>TRUE, BINDS=>TRUE);
SQL> EXEC DBMS_SUPPORT.STOP_TRACE_IN_SESSION (SID=>123, SERIAL=>1234);
Verses >= 10G
SQL> EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE
(SESSION_ID =>1234, SERIAL_NUM=>1234, WAITS=>TRUE, BINDS=>FALSE);
SQL> EXEC DBMS_MONITOR.SESSION_TRACE_DISABLE (SESSION_ID=>1234, SERIAL_NUM=>1234);
SQL> EXEC DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE
(CLIENT_ID=>'PORTILHO', WAITS=>TRUE, BINDS=>TRUE);
SQL> EXEC DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE(CLIENT_ID=>'PORTILHO');
SQL> EXEC DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE
(SERVICE_NAME=>'OLTP', MODULE_NAME=>'TESTE', ACTION_NAME=>'RUNNING',
WAITS=>TRUE, BINDS=>TRUE);
SQL> EXEC DBMS_MONITOR.SERV_MOD_ACT_TRACE_DISABLE
(SERVICE_NAME=>'OLTP', MODULE_NAME=>'TESTE', ACTION_NAME=>'RUNNING');
SQL> ALTER SESSION SET EVENTS 'trace[rdbms.SQL_Optimizer.*][sql:sql_id]';

41

SQL Trace (Event 10046): Ativao

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';
OU
SQL> SELECT P.SPID, P.TRACEFILE
FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';
SQL> oradebug setospid 9999;
SQL> oradebug tracefile_name;
SQL> oradebug unlimit;
SQL> oradebug event 10046 trace name context forever, level 12;

42

SQL Trace (Event 10046): tkprof


$ tkprof
Usage: tkprof tracefile outputfile [explain= ] [table= ]
[print= ] [insert= ] [sys= ] [sort= ]
table=schema.tablename
Use 'schema.tablename' with 'explain=' option.
explain=user/password
Connect to ORACLE and issue EXPLAIN PLAN.
print=integer
List only the first 'integer' SQL statements.
aggregate=yes|no
insert=filename List SQL statements and data inside INSERT statements.
sys=no
TKPROF does not list SQL statements run as user SYS.
record=filename Record non-recursive statements found in the trace file.
waits=yes|no
Record summary for any wait events found in the trace file.
sort=option
Set of zero or more of the following sort options:
prscnt number of times parse was called
prscpu cpu time parsing
prsela elapsed time parsing
prsdsk number of disk reads during parse
prsqry number of buffers for consistent read during parse
prscu
number of buffers for current read during parse
prsmis number of misses in library cache during parse
...

43

SQL Trace (Event 10053)


SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT OFF';
OU
SQL> SELECT P.SPID, P.TRACEFILE
FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';
SQL> oradebug setospid 9999;
SQL> oradebug tracefile_name;
SQL> oradebug unlimit;
SQL> oradebug event 10053 trace name context forever, level 1;

44

Lab 2 SQL Trace


Hands On !

45

Lab 2.1: SQL Trace (Event 10046)

SQL> CONN SCOTT/TIGER


SQL> SELECT P.SPID, P.TRACEFILE
FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7369;
SQL> SELECT * FROM EMP;
SQL> CREATE TABLE T21 AS SELECT * FROM ALL_OBJECTS;

46

Lab 2.2: tkprof (Event 10046)

47

Lab 2.3: SQL Trace (Event 10046)

48

Lab 2.4: SQL Trace (Event 10053)


SQL> CONN SCOTT/TIGER
SQL> SELECT P.SPID, P.TRACEFILE
FROM V$SESSION S, V$PROCESS P
WHERE S.PADDR = P.ADDR AND S.USERNAME = 'SCOTT';
SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> SELECT EMPNO, ENAME, DNAME, LOC
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

49

Lab 2.5: SQL Trace (Event 10053)

50

Lab 2.6: SQL Trace (Event 10053)

51

Lab 2.7: SQL Trace (Event 10053)

52

Lab 2.8: SQL Trace (Event 10053)

53

Lab 2.9: SQL Trace (Event 10053)

54

Lab 2.10: SQL Trace (Event 10053)

55

Lab 2.11: SQL Trace (Event 10053)

56

Lab 2.12: SQL Trace (Event 10053)

57

Lab 2.13: SQL Trace (Event 10053)

58

Lab 2.14: SQL Trace (Event 10053)

59

Lab 2.15: SQL Trace (Event 10053)

60

SQL Engine

61

Terminologia
Soft Parse / Hard Parse
LIO (Logical Input/Output)

PIO (Physical Input/Output)

Latch / Mutex

Buffer Cache

Shared Pool

Library Cache

62

PGA

63

SELECT
5: SELECT (COLUMN / DISTINCT COLUMN / expression / scalar subquery)
1: FROM / FROM JOIN ON (fontes: TABLE, VIEW, MVIEW, PARTITION, SUBQUERY...)
2: * WHERE (condies: TRUE, FALSE, UNKNOWN)
3: * GROUP BY (opes: ROLLUP / CUBE)
4: * HAVING (condio: TRUE)
6: * ORDER BY (COLUMN)
Exemplo:
SELECT C.CUSTOMER_ID, COUNT(O.ORDER_ID) AS ORDER_CT
FROM
OE.CUSTOMERS C
JOIN OE.ORDERS O ON C.CUSTOMER_ID = O.CUSTOMER_ID
WHERE C.GENDER = 'F'
GROUP BY C.CUSTOMER_ID
HAVING COUNT(O.ORDER_ID) > 4
ORDER BY ORDERS_CT, C_CUSTOMER_ID;

Na fase 2, os dados j foram selecionados (IN MEMORY Column Store).

64

Processamento de SQL
OPEN CURSOR
PARSE

BIND

EXEC

FETCH (ARRAYSIZE, DEFAULT_SDU_SIZE (512 a 32767), RECV_BUF_SIZE, SEND_BUF_SIZE)

CLOSE CURSOR

SQL*Net
PARSE
SQL*Net
SQL*Net
BIND
SQL*Net
SQL*Net
EXEC
SQL*Net
SQL*Net
FETCH
SQL*Net
SQL*Net
FETCH
SQL*Net
SQL*Net
...

Message From Client


Message To Client
Message From Client
Message To Client
Message From Client
Message To Client
Message From Client
Message To Client
Message From Client
Message To Client
Message From Client

Apenas SELECT possui a fase FETCH.

65

Processamento de SQL

66

PL/SQL Engine

67

SQL Recursivos

68

SQL Recursivos

69

Hard Parse / Soft Parse

70

Hard Parse / Soft Parse

71

Lab 3 SQL Engine


Hands On !

72

Lab 3.1: FETCH


Execute os comandos abaixo.

SQL> CONN HR/HR


SQL> SET AUTOTRACE TRACEONLY STATISTICS
SQL> SELECT * FROM EMPLOYEES;
107 rows selected.
Statistics
---------------------------------------------------------1 recursive calls
0 db block gets
15 consistent gets
6 physical reads
0 redo size
10499 bytes sent via SQL*Net to client
629 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed

73

Lab 3.2: FETCH


Execute os mesmo SELECT anterior, mas com o ARRAYSIZE diferente.
HR> SET ARRAYSIZE 100
HR> SELECT * FROM EMPLOYEES;
107 rows selected.
Statistics
---------------------------------------------------------0 recursive calls
0 db block gets
9 consistent gets
0 physical reads
0 redo size
9335 bytes sent via SQL*Net to client
563 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed

74

Lab 3.3: Shared Pool


Reinicie a instncia, e execute os comandos abaixo.
SQL> CONN / AS SYSDBA
SQL> SHUTDOWN IMMEDIATE
SQL> STARTUP
SQL> CONN SCOTT/TIGER
SQL> SET AUTOTRACE TRACEONLY STATISTICS
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7369;
104 recursive calls
0 db block gets
164 consistent gets
7 physical reads
0 redo size
550 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
9 sorts (memory)
0 sorts (disk)
1 rows processed

75

Lab 3.4: Shared Pool


Execute novamente o mesmo SELECT.
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7369;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
550 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

76

Lab 3.5: Shared Pool


Execute o mesmo SQL, duas vezes, mas solicitando outro registro.
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7499;
36 recursive calls
0 db block gets
53 consistent gets
0 physical reads
0 redo size
550 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7499;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
550 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

77

Lab 3.6: Shared Pool


Execute o mesmo SQL, tambm duas vezes, mas solicitando outro registro.
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7521;
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
549 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7521;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
549 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

78

Lab 3.7: Shared Pool


Execute o seguinte SQL, tambm duas vezes.

SQL> SELECT ENAME FROM EMP WHERE EMPNO IN (7654, 7698, 7782);
5 recursive calls
0 db block gets
13 consistent gets
2 physical reads
0 redo size
619 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed
SQL> SELECT ENAME FROM EMP WHERE EMPNO IN (7654, 7698, 7782);
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
619 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed

79

Lab 3.8: Shared Pool


Remova as estatsticas da tabela, e execute o primeiro SQL, tambm duas vezes.
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT', 'EMP');
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7369;
0 recursive calls
0 db block gets
2 consistent gets
16 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT ENAME FROM EMP WHERE EMPNO = 7369;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
1 rows processed

80

Lab 3.9: Shared Pool


Execute o SQL abaixo, que retorna mais dados, tambm duas vezes.
SQL> SELECT * FROM DEPT;
40 recursive calls
0 db block gets
88 consistent gets
41 physical reads
0 redo size
...
6 sorts (memory)
0 sorts (disk)
4 rows processed

SQL> SELECT * FROM DEPT;


0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
4 rows processed

81

Lab 3.10: Shared Pool


Limpe a Shared Pool, e execute novamente o SQL, tambm duas vezes.
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
SQL> SELECT * FROM DEPT;
1a execuo:
71 recursive calls
0 db block gets
90 consistent gets
0 physical reads
0 redo size
...
6 sorts (memory)
0 sorts (disk)
4 rows processed
SQL> SELECT * FROM DEPT;
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
4 rows processed

82

Lab 3.11: Shared Pool


Execute novamente o primeiro SQL, mas com variveis Bind, tambm duas vezes.
SQL> VARIABLE vEMPNO NUMBER
SQL> EXEC :vEMPNO := 7369
SQL> SELECT ENAME FROM EMP WHERE EMPNO = :vEMPNO;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
...
1 rows processed
SQL> EXEC :vEMPNO := 7499
SQL> SELECT ENAME FROM EMP WHERE EMPNO = :vEMPNO;
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
...
1 rows processed

83

Lab 3.12: Hard Parse / Soft Parse


Execute novamente o SELECT na DEPT, verificado os Parses.

SQL> SET AUTOTRACE OFF


SQL> SELECT S.NAME, M.VALUE FROM V$STATNAME S, V$MYSTAT M WHERE S.STATISTIC# =
M.STATISTIC# AND S.NAME IN ('parse count (total)', 'parse count (hard)');
parse count (total)
30
parse count (hard)
6
SQL> SELECT * FROM DEPT;
...
parse count (total)
parse count (hard)

32
6

SQL> SELECT * FROM DEPT;


...
parse count (total)
parse count (hard)

34
6

SQL> SELECT * FROM DEPT ORDER BY 1;


...
parse count (total)
parse count (hard)

43
7

SQL> SELECT * FROM DEPT ORDER BY 1,2;


...
parse count (total)
parse count (hard)

45
8

84

Lab 3.13: Buffer Cache


Limpe o Buffer Cache, e execute novamente o SQL da DEPT, tambm duas vezes.
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
SQL> SET AUTOTRACE TRACEONLY STATISTICS
SQL> SELECT * FROM DEPT;
1a execuo:
0 recursive calls
0 db block gets
8 consistent gets
6 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
4 rows processed
2a execuo:
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
...
0 sorts (memory)
0 sorts (disk)
4 rows processed

85

Lab 3.14: Connect / Parse / Commit


Crie a tabela abaixo com o usurio SCOTT.
SQL> CREATE TABLE T314 (C1 NUMBER);

Observe o contedo dos seguintes scripts Perl, os execute, e compare.


$
$
$
$
$
$
$
$
$
$

time
time
time
time
time
time
time
time
time
time

perl
perl
perl
perl
perl
perl
perl
perl
perl
perl

/home/oracle/ConnectBAD_CommitBAD_BindsBAD.pl 5000
/home/oracle/ConnectBAD_CommitBAD_BindsGOOD.pl 5000
/home/oracle/ConnectBAD_CommitGOOD_BindsBAD.pl 5000
/home/oracle/ConnectBAD_CommitGOOD_BindsGOOD.pl 5000
/home/oracle/ConnectGOOD_CommitBAD_BindsBAD.pl 5000
/home/oracle/ConnectGOOD_CommitBAD_BindsGOOD.pl 5000
/home/oracle/ConnectGOOD_CommitGOOD_BindsBAD.pl 5000
/home/oracle/ConnectGOOD_CommitGOOD_BindsBAD_ONE.pl 5000
/home/oracle/ConnectGOOD_CommitGOOD_BindsGOOD.pl 5000
/home/oracle/ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 5000

Re-execute o ConnectGOOD_CommitGOOD_BindsBAD.pl, mas em sesses


concorrentes.
10 x $ time perl /home/oracle/ConnectGOOD_CommitGOOD_BindsBAD.pl 5000 &

Re-execute os testes ConnectGOOD com os parmetros abaixo alterados.


ALTER SYSTEM SET CURSOR_SHARING=FORCE;
ALTER SYSTEM SET COMMIT_LOGGING=BATCH;

86

Lab 3.15: PL/SQL Engine


Crie esta tabela com o usurio SCOTT:
SQL> CREATE TABLE T315 (C1 NUMBER);

Observe o contedo dos seguintes scripts Perl, os execute, e compare:


$ time perl /home/oracle/SemPLSQL.pl 5000
$ time perl /home/oracle/ComPLSQL.pl 5000

87

Access Paths

88

Access Paths

Full Table Scan (FTS)


Table Access by ROWID
Index Unique Scan
Index Range Scan
Index range scan descending
Index Skip Scan
Full Index Scan (FIS)
Fast Full Index Scan (FFIS)

89

Full Table Scan


Depende de:
Percentual de dados que sero acessados;
Quantidade de blocos lidos em leituras mltiplas (db_file_multiblock_read_count);
Velocidade de leitura de mltiplos blocos x nico bloco (System Statistics);
Distribuio das linhas nos blocos;
HWM.

90

MBRC: scatteread / sequential


Ocorre db file sequential read quando:
- O bloco est no final do Extent;
- O bloco j est no cache;
- Excede o limite do sistema operacional;
- UNDO.

91

Lab 4.1: FTS e Clustering Factor


Crie as duas tabelas abaixo com o usurio SCOTT, e compare as duas.
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T1 AS
SELECT TRUNC((ROWNUM-1)/100) ID, RPAD(ROWNUM,100) NAME
FROM DBA_SOURCE
WHERE ROWNUM <= 10000;
SQL> CREATE INDEX T1_IDX1 ON T1(ID);
SQL> CREATE TABLE T2 AS
SELECT MOD(ROWNUM,100) ID, RPAD(ROWNUM,100) NAME
FROM DBA_SOURCE
WHERE ROWNUM <= 10000;
SQL> CREATE INDEX T2_IDX1 ON T2(ID);
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

SELECT
SELECT
SELECT
SELECT
SELECT
SELECT
SELECT
SELECT

COUNT(*) FROM T1;


COUNT(*) FROM T2;
MIN(ID) FROM T1;
MIN(ID) FROM T2;
MAX(ID) FROM T1;
MAX(ID) FROM T2;
COUNT(*) FROM T1 WHERE ID = 1;
COUNT(*) FROM T2 WHERE ID = 1;

92

Lab 4.2: FTS e Clustering Factor


Compare os planos de execuo de SQL iguais para as duas tabelas.
SQL> SET AUTOTRACE TRACEONLY EXPLAIN
SQL> SELECT ID, NAME FROM T1 WHERE ID = 1;
SQL> SELECT ID, NAME FROM T2 WHERE ID = 1;
SQL> SELECT ID, NAME FROM T1 WHERE ID < 5;
SQL> SELECT ID, NAME FROM T2 WHERE ID < 5;
SQL> SELECT ID, NAME FROM T1 WHERE ID < 10;
SQL> SELECT ID, NAME FROM T2 WHERE ID < 10;
Verifique a ordenao fsica dos dados das tabelas.
SQL> SET AUTOTRACE OFF
SQL> SELECT ID, NAME FROM T1;
SQL> SELECT ID, NAME FROM T2;
SQL> SELECT ROWID, ID, NAME FROM T1 ORDER BY 2;
SQL> SELECT ROWID, ID, NAME FROM T2 ORDER BY 2;

93

Lab 4.3: FTS e Clustering Factor


Compare as estatsticas das duas tabelas.
SQL> SET AUTOTRACE OFF
SQL> COL TABLE_NAME FORMAT A20
SQL> COL INDEX_NAME FORMAT A20
SQL> SELECT
T.TABLE_NAME,
I.INDEX_NAME,
I.CLUSTERING_FACTOR,
T.BLOCKS,
T.NUM_ROWS
FROM DBA_TABLES T, DBA_INDEXES I
WHERE T.TABLE_NAME = I.TABLE_NAME AND
T.TABLE_NAME IN ('T1', 'T2') AND
T.OWNER = 'SCOTT'
ORDER BY T.TABLE_NAME, I.INDEX_NAME;

94

Lab 4.4: FTS e HWM


Compare as estatsticas deste SELECT, antes e depois do DELETE.
SQL> CREATE TABLE T4 AS SELECT * FROM ALL_OBJECTS;
SQL> SET AUTOTRACE TRACEONLY
SQL> SELECT COUNT(*) FROM T4;
SQL> SELECT COUNT(*) FROM T4;
SQL> SELECT COUNT(*) FROM T4;
SQL>
SQL>
SQL>
SQL>

DELETE
SELECT
SELECT
SELECT

FROM T4;
COUNT(*) FROM T4;
COUNT(*) FROM T4;
COUNT(*) FROM T4;

95

Lab 4.5: FTS e HWM


Verifique os blocos utilizados pela tabela, antes e depois do DELETE.
SQL> SET AUTOTRACE OFF
SQL> DROP TABLE T4;
SQL> CREATE TABLE T4 AS SELECT * FROM ALL_OBJECTS;
SQL> SELECT MIN(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MIN_BLK,
MAX(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MAX_BLK FROM T4;
SQL> DELETE FROM T4;
SQL> SELECT MIN(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MIN_BLK,
MAX(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MAX_BLK FROM T4;
SQL> ROLLBACK;
SQL> SELECT MIN(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MIN_BLK,
MAX(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) MAX_BLK FROM T4;

96

Index Scan

Index Unique Scan


Index Range Scan
Index Skip Scan
Index Full Scan
Index Fast Full Scan

Por que ler todos blocos de um ndice E os da tabela, e no s os da tabela?

97

Index Scan

B-tree = rvore Balanceada


Root Block / Branch Blocks / Leaf Blocks
Height / BEVEL (quando o Height / BLEVEL aumenta?)
Average Leaf Blocks per Key / Average Data Blocks per Key
Clustering Factor

98

Lab 5.1: Index Scan


Compare as estatsticas destes SELECTs.

SQL> SET AUTOTRACE TRACEONLY STATISTICS


SQL> SELECT NAME FROM T1 WHERE ID = 0 AND NAME = 1;
0 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
636 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT COUNT(NAME) FROM T1 WHERE ID = 0 AND NAME = 1;
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
545 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

99

Lab 5.2: Index Scan


Compare as estatsticas deste SELECTs, com os do Lab 5.1.
SQL> SELECT NAME FROM T2 WHERE ID = 0 AND NAME = 1;
0 recursive calls
0 db block gets
156 consistent gets
0 physical reads
0 redo size
348 bytes sent via SQL*Net to client
540 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

SQL> SELECT COUNT(NAME) FROM T2 WHERE ID = 0 AND NAME = 1;


0 recursive calls
0 db block gets
156 consistent gets
0 physical reads
0 redo size
552 bytes sent via SQL*Net to client
551 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

100

Lab 5.3: Index Scan


Compare as estatsticas deste SELECTs.

SQL> SELECT NAME FROM T1 WHERE ID = 1;


1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
11484 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed
SQL> SELECT NAME FROM T2 WHERE ID = 1;
1 recursive calls
0 db block gets
157 consistent gets
0 physical reads
0 redo size
11176 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed

101

Index Unique Scan

102

Index Unique Scan


Utilizado com Primary Key ou Unique Key;
Consistent Gets mnimo = (Rows x 2) + BLEVEL + 1.

103

Index Range Scan

104

Index Range Scan


Utilizado com Primary Key, Unique Key, ou Non-unique Key;
Consistent Gets mnimo = (Rows x 2) + BLEVEL + 1.

105

Index Range Scan - Sort

106

Index Full Scan

107

Index Full Scan


Utilizado quando:
No h predicado, mas uma das colunas est indexada;
Predicado no a primeira coluna de um ndice;
Um ndice pode economizar um SORT.

108

Index Full Scan


Sem predicado, mas uma das colunas est indexada;
Predicado no a primeira coluna de um ndice;
Um ndice pode economizar um SORT.

109

Index Full Scan


Sem predicado, mas uma das colunas est indexada;
Predicado no a primeira coluna de um ndice;
Um ndice pode economizar um SORT.

110

Index Full Scan


Sem predicado, mas uma das colunas est indexada;
Predicado no a primeira coluna de um ndice;
Um ndice pode economizar um SORT.

111

Index Full Scan

112

Index Full Scan

113

Index Skip Scan


O predicado contm uma condio em uma coluna indexada, mas esta coluna no
a primeira do ndice, e as primeiras colunas tem um baixo NDV.

114

Index Fast Full Scan


Utilizado quando todas as colunas do SELECT esto includas no ndice;
Utiliza MBRC;

No h acesso tabela;

No pode ser utilizado para evitar um SORT.

115

Query Transformation

116

Query Rewrite
De acordo com a Documentao:

OR Expansion

View Merging

Predicate Pushing

Subquery Unnesting

In-Memory Aggregation

Table Expansion

Join Factorization

Query Rewrite with Materialized Views

Star Transformation

117

Query Rewrite

Controle: Hints QUERY_TRANSFORMATION / NO_QUERY_TRANSFORMATION

SQL>
SQL>
SQL>
FROM

CONN HR/HR
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID
DEPARTMENTS);

118

View Merging
Controle: MERGE / NO_MERGE / Parmetro _complex_view_merging (TRUE de 9i em diante).
Geralmente utilizada quando o Outer Query Block contm:
- Uma coluna que pode ser utilizada em um ndice com outro Query Block;
- Uma coluna que pode ser utilizada para Partition Pruning com outro Query Block;
- Uma condio que limita as linhas retornadas de uma das tabelas em uma Joined View.
Geralmente no ser utilizada se:
- Um Query Block contiver uma funo de agregao ou analtica;
- Um Query Block contiver Set Operations (UNION, INTERSECT, MINUS);
- Um Query Block contiver ORDER BY;
- Um Query Block contiver ROWNUM.

Fomos treinados para entender que estas duas expresses retornam resultados diferentes:

6+4/2=8

(6 + 4) / 2 = 5

119

Lab 6.1: View Merging


Execute o SELECT abaixo, e encontre no arquivo trace o View Merging.

SQL> CONN OE/OE


SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> SELECT * FROM ORDERS O, (SELECT SALES_REP_ID FROM ORDERS) O_VIEW
WHERE O.SALES_REP_ID = O_VIEW.SALES_REP_ID (+)
AND O.ORDER_TOTAL > 100000;

Execute o SELECT abaixo, e encontre no arquivo trace o View Merging.


SQL> CONN OE/OE
SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> SELECT * FROM ORDERS O, (SELECT SALES_REP_ID FROM ORDERS ORDER BY
SALES_REP_ID) O_VIEW WHERE O.SALES_REP_ID = O_VIEW.SALES_REP_ID (+) AND
O.ORDER_TOTAL > 100000 AND ROWNUM < 10 ORDER BY ORDER_TOTAL;

120

Subquery Unnesting
- Controle: HINT NO_UNNEST, unnest_subquery (TRUE de 9i em diante).
- Similar a View Merging, ocorre quando a Subquery est localizada na clusula WHERE;
- A transformao mais comum em um JOIN;
SQL>
SQL>
SQL>
FROM

CONN HR/HR
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID
DEPARTMENTS);

121

Subquery Unnesting + JE

O plano de execuo utiliza quais tabelas?

122

Lab 6.2: Subquery Unnesting


Execute o SELECT abaixo, e encontre no arquivo trace o Subquery Unnesting.

SQL> CONN HR/HR


SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> SELECT
OUTER.EMPLOYEE_ID,
OUTER.LAST_NAME,
OUTER.SALARY,
OUTER.DEPARTMENT_ID
FROM EMPLOYEES OUTER
WHERE OUTER.SALARY >
(SELECT AVG(INNER.SALARY)
FROM EMPLOYEES INNER
WHERE INNER.DEPARTMENT_ID = OUTER.DEPARTMENT_ID);

123

Lab 6.3: Subquery Unnesting

124

Predicate Pushing
- Controle: Hints PUSH_PRED / NO_PUSH_PRED.
- Geralmente utilizado para aplicar os predicados de um Query Block em outro Query
Block, quando no pode ocorrer uma transformao de Merging, para permitir a
utilizao de um ndice e filtrar mais cedo no plano de execuo;

125

Lab 6.4: Predicate Pushing


Execute o SELECT abaixo, e encontre no arquivo trace o Predicate Pushing.
SQL> CONN HR/HR
SQL> ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SQL> SELECT E1.LAST_NAME, E1.SALARY, V.AVG_SALARY
FROM EMPLOYEES E1,
(SELECT DEPARTMENT_ID, AVG(SALARY) AVG_SALARY
FROM EMPLOYEES E2
GROUP BY DEPARTMENT_ID) V
WHERE E1.DEPARTMENT_ID = V.DEPARTMENT_ID
AND E1.SALARY > V.AVG_SALARY
AND E1.DEPARTMENT_ID = 60;

E com DEPARTMENT_ID IN (10,40,60)?

126

Join Methods & Options

127

Join Methods
Nested Loops
Hash Joins
Sort-merge Joins
Driving Table (Outer / maior / PK / UNIQUE) / Inner Table (menor):

128

Join Options

Inner Join
Outer Join
Cross Join / Cartesian Joins
Semi-Join
Anti-Join

129

Nested Loops

um LOOP dentro de um LOOP.


mais eficiente com pequenos Result Sets;
Geralmente ocorre quando h ndices nas colunas utilizadas pelo Join;
Utiliza pouca memria, pois o Result Set construdo uma linha por vez;
HINT: /*+ USE_NL(EMP DEPT) */

SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO =
DEPT.DEPTNO AND DEPT.DEPTNO IN (10);
SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO =
DEPT.DEPTNO AND DEPT.DEPTNO IN (10,20);
SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO =
DEPT.DEPTNO;

130

Sort-Merge Joins

131

Sort-Merge Joins
L as duas tabelas de forma independente, ordena, e junta os Result Sets,
descartando linhas que no combinam;
Geralmente utilizado para Result Sets maiores, e quando no h ndices;
Geralmente utilizado quando uma operao de desigualdade;
O maior custo a ordenao;
Poder ser utilizada apenas PGA, ou pode ser necessrio TEMP;
HINTs: USE_MERGE / NO_USE_MERGE

SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO =
DEPT.DEPTNO AND DEPT.DEPTNO NOT IN (10);

132

Hash Joins
S ocorre em equi-joins;
Geralmente utilizado para grandes Result Sets;

Geralmente utilizado se o menor Result Set cabe em memria;

A tabela com o menor Result Set lida e armanezada em memria como um HASH;

Em seguida a outra tabela (maior Result Set) lida, aplicado o HASH, e ento
comparada com a menor;

Poder ser utilizada apenas PGA, ou pode ser necessrio TEMP;

133

Hash Joins

134

Cartesian Joins / Cross Joins


Geralmente trata-se da ausncia de condio do Join (DISTINCT!);
O tamanho do resultado o produto dos dois Result Sets;

Poder ser utilizada apenas PGA, ou pode ser necessrio TEMP.

O BUFFER SORT de um Cartesian Join no um SORT.

135

Cartesian Joins / Cross Joins

SQL> SELECT T1.ID, T2.NAME FROM T1, T2 WHERE T1.ID = T2.ID;

136

Outer Joins
Sintaxe Oracle: (+);
A sintaxe Oracle no suporta FULL OUTER JOIN;

Sintaxe ANSI: LEFT [OUTER] JOIN / RIGHT [OUTER] JOIN;

Um OUTER JOIN pode utilizar qualquer mtodo de JOIN;

12c: Multi-table LEFT OUTER JOIN.

137

Semi-Joins (IN)
Controle: HINTs SEMIJOIN, NO_SEMIJOIN, NL_SJ, MERGE_SJ, HASH_SJ
Uma otimizao de INNER JOIN, de custo menor;

Utilizado em listas IN ou EXISTS;

necessrio utilizar uma Subquery;

Se for utilizado EXISTS, necessrio utilizar uma Correlated Subquery;

As clusulas IN ou EXISTS no podem estar dentro de um OR.

SQL> CONN HR/HR


SQL> SELECT DEPARTMENT_NAME
FROM DEPARTMENTS DEPT
WHERE DEPARTMENT_ID IN
(SELECT DEPARTMENT_ID FROM HR.EMPLOYEES EMP);

138

Semi-Joins (EXISTS)
SQL> CONN HR/HR
SQL> SELECT DEPARTMENT_NAME
FROM DEPARTMENTS DEPT
WHERE EXISTS
(SELECT NULL
FROM HR.EMPLOYEES EMP
WHERE EMP.DEPARTMENT_ID = DEPT.DEPARTMENT_ID);

139

Anti-Joins (NOT IN)


Uma otimizao de INNER JOIN, de custo menor;
Utilizado em listas NOT IN ou NOT EXISTS;

necessrio utilizar uma Subquery;

Se for utilizado NOT EXISTS, necessrio utilizar uma Correlated Subquery;

As clusulas NOT IN ou NOT EXISTS no podem estar dentro de um OR;

A Subquery no pode retornar NULL (<=10g) (SNA).

Controle: HINTs ANTIJOIN, NL_AJ, MERGE_AJ, HASH_AJ

Controle: Parmetros _always_anti, _gs_anti_semi_join_allowed,


_optimizer_null_aware_antijoin, _optimizer_outer_to_anti_enabled

140

Anti-Joins (NOT IN)


SQL> SELECT * FROM EMPLOYEES
WHERE DEPARTMENT_ID NOT IN
(SELECT DEPARTMENT_ID
FROM DEPARTMENTS
WHERE LOCATION_ID = 1700)
ORDER BY LAST_NAME;

141

Anti-Joins (NOT EXISTS)


SQL> SELECT DEPARTMENT_NAME
FROM DEPARTMENTS DEPT
WHERE NOT EXISTS
(SELECT NULL
FROM EMPLOYEES EMP
WHERE EMP.DEPARTMENT_ID = DEPT.DEPARTMENT_ID);

142

Bloom Filters
Controle: HINTs PX_JOIN_FILTER, NO_PX_JOIN_FILTER;
Utiliza pouca memria para o filtro em relao do conjunto de dados;

mais utilizado quando a maioria das linhas so descartadas em um JOIN;

Reduz a quantidade de dados transferidos entre processos paralelos;

mais utilizado se mais parties forem eliminadas por Partition Pruning;

Utiliza Result Cache;

utilizado em Exatada, especialmente em JOINs em STAR SCHEMAs.

143

Partition-wise Joins

No partition-wise join

144

Partition-wise Joins

Full partition-wise join


Partial partition-wise joins

145

ndices

146

ndices

B-tree
Bitmap
Bitmap Join
IOT (Index-Organized Table)
Function-Based
Invisible Indexes (11g / OPTIMIZER_USE_INVISIBLE_INDEXES)
Virtual Indexes
Partitioned Indexes
Partial Indexes (12c)
Domain Indexes
Compressed
Ascending / Descending
Table Clusters

147

ndices
Bitmap Join
SQL> CREATE BITMAP INDEX cust_sales_bji
ON
sales(customers.state)
FROM sales, customers
WHERE sales.cust_id = customers.cust_id;
IOT
CREATE TABLE locations
(id
NUMBER(10)
NOT NULL,
description VARCHAR2(50) NOT NULL,
map
BLOB,
CONSTRAINT pk_locations PRIMARY KEY (id)
)
ORGANIZATION INDEX
TAB LESPACE iot_tablespace
PCTTHRESHOLD 20
INCLUDING description
OVERFLOW TABLESPACE overflow_tablespace;

148

ndices
Invisible
SQL> ALTER INDEX IDX_T INVISIBLE;
SQL> ALTER INDEX IDX_T VISIBLE;
Virtual
SQL> CREATE INDEX IDX_T ON T(OBJECT_NAME) NOSEGMENT;
Function Based
SQL> CREATE INDEX IDX_T ON T(UPPER(OBJECT_NAME));
Partial Index
SQL> ALTER TABLE T1 MODIFY PARTITION
SQL> CREATE INDEX T1_IDX ON T1(YEAR)
SQL> CREATE INDEX T1_IDX ON T1(YEAR)
SQL> CREATE INDEX T1_IDX ON T1(YEAR)
SQL> CREATE INDEX T1_IDX ON T1(YEAR)
SQL> CREATE INDEX T1_IDX ON T1(YEAR)
SQL> CREATE INDEX T1_IDX ON T1(YEAR)

ANO_2014 INDEXING OFF;


LOCAL;
LOCAL INDEXING FULL;
LOCAL INDEXING PARTIAL;
GLOBAL;
GLOBAL INDEXING FULL;
GLOBAL INDEXING PARTIAL;

149

ndices - Guidelines
Geral

Controle: HINTs INDEX, INDEX_COMBINE, NO_INDEX, FULL;

Crie ndices em colunas utilizadas na clusula WHERE;

Crie ndices em colunas utilizadas em JOINs;

Crie ndices em colunas de alta seletividade;

Crie ndices em colunas de baixa seletividade mas que contenham dados com
seletividades muito distintas;

Prefira ndices PRIMARY KEY, se o modelo permitir;

Prefira ndices UNIQUE, se o modelo permitir, mas PRIMARY KEY no possvel;

Crie ndices compostos em colunas utilizadas frequentemente na mesma clusula


WHERE;

Em ndices compostos, utilize as colunas com maior seletividade esquerda;

Se um valor de uma coluna indexada no for utilizado em uma clusula WHERE,


verifique se este valor pode ser trocado para NULL;

Busque sempre minimizar a quantidade de ndices de uma tabela;

Considere o espao utilizado por um ndice (60% - 40%).

150

ndices - Guidelines
DML

Crie ndices em Foreign Keys (FKs) que sofrem DML de forma concorrente;

Evite ndices em colunas que sofrem muitos UPDATEs;

Evite ndices em tabelas que sofrem muitos INSERTs ou DELETEs.


Tipos

Prefira ndices BTREE em colunas de alta seletividade (CPF, NF);

Prefira ndices BITMAP em colunas de baixa seletividade (ESTADO, CIDADE);

Evite ndices em colunas utilizadas em clusula WHERE apenas com funes;

Utilize ndices de funo em colunas utilizadas em clusula WHERE mais


frequentemente com funes;

Prefira ndices BITMAP para grandes tabelas;

Evite ndices BITMAP em colunas que sofrem muito DML, principalmente de forma
concorrente;

Prefira parties HASH em ndices pequenos que sofrem DML em alta concorrncia;

Utilize IOTs em PKs frequentemente utilizadas na clusula WHERE.

151

ndices - Table Clusters

Utilize se as tabelas so frequentemente utilizadas em JOINs (NF e ITEM_NF);


Utilize se as tabelas sofrem mais JOINs do que operaes DML;
Evite se utilizado FTS de apenas uma das tabelas;
Evite para linhas largas (PEDIDO_NOTA_FISCAL com OBS);
Evite se o nmero de linhas nas chaves das duas tabelas muito diferente.

152

BITMAP x BTREE
SQL> SELECT COUNT(*) FROM T4;
COUNT(1)

10936000

- - Sem ndice.

SQL> SELECT COUNT(DISTINCT(OWNER)) FROM T; - - Sem ndice.


COUNT(DISTINCT(OWNER))

28
Decorrido: 00:00:26.75
SQL> SELECT COUNT(DISTINCT(OWNER)) FROM T; - - Com ndice BTREE.
COUNT(DISTINCT(OWNER))

28
Decorrido: 00:00:05.29
SQL> SELECT COUNT(DISTINCT(OWNER)) FROM T; - - Com ndice BITMAP.
COUNT(DISTINCT(OWNER))

28
Decorrido: 00:00:01.84

153

BITMAP x BTREE
SQL> SELECT COUNT(*) FROM T;
COUNT(1)

10936000
SQL> SELECT COUNT(DISTINCT(OWNER)) FROM T;
COUNT(DISTINCT(OWNER))

28
SQL> SELECT COUNT(DISTINCT(OBJECT_NAME)) FROM T; -- Com ndice BTREE
COUNT(DISTINCT(OBJECT_NAME))

40998
Decorrido: 00:00:08.95
SQL> SELECT COUNT(DISTINCT(OBJECT_NAME)) FROM T; Com ndice BITMAP
COUNT(DISTINCT(OBJECT_NAME))

40998
Decorrido: 00:00:03.15

154

ndices e Access Paths

155

ndices e Access Paths

156

Lab 7.1: DML e BITMAP Index


1a Sesso:

2a Sesso:

SQL> CREATE BITMAP INDEX


IDX_BITMAP_T314 ON T314(C1);
SQL> INSERT INTO T314 VALUES (1);
SQL> COMMIT;

SQL> INSERT INTO T314 VALUES (10);


SQL> COMMIT;

SQL> INSERT INTO T314 VALUES (1);


SQL> COMMIT;

SQL> INSERT INTO T314 VALUES (1);


COMMIT;

SQL> INSERT INTO T314 VALUES (1);


SQL> INSERT INTO T314 VALUES (10);

SQL> INSERT INTO T314 VALUES (10);


SQL> INSERT INTO T314 VALUES (1);

157

Lab 7.2: Impacto de ndices


Execute novamente o melhor script de INSERT, mas com a adio de ndices
como abaixo.
$
$
$
$

cd /home/oracle
time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000

SQL> DROP INDEX IDX_BITMAP_T314;


SQL> CREATE INDEX IDX_BTREE_T314 ON T314(C1);
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
SQL> DROP INDEX IDX_BTREE_T314;
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000
$ time perl ConnectGOOD_CommitGOOD_BindsGOOD_PERFECT.pl 10000

158

Lab 7.3: Impacto de ndices


Com o usurio SCOTT, crie uma tabela de testes, e verifique o tempo de sua
duplicao.
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

CREATE TABLE T7 AS SELECT * FROM ALL_OBJECTS;


INSERT INTO T7 SELECT * FROM T7;
INSERT INTO T7 SELECT * FROM T7;
INSERT INTO T7 SELECT * FROM T7;
INSERT INTO T7 SELECT * FROM T7;
COMMIT;

SQL> CREATE TABLE T8 AS SELECT * FROM T7 WHERE 1=0;


SQL> SET TIMING ON
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

INSERT INTO T8
TRUNCATE TABLE
INSERT INTO T8
TRUNCATE TABLE
INSERT INTO T8
TRUNCATE TABLE

SELECT * FROM T7;


T8;
SELECT * FROM T7;
T8;
SELECT * FROM T7;
T8;

159

Lab 7.4: Impacto de ndices


Verifique o tempo de sua duplicao, mas com ndices.
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

CREATE INDEX T8_IDX_01 ON T8(OWNER);


INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;

SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

CREATE INDEX T8_IDX_02 ON T8(OBJECT_NAME);


INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;

160

Lab 7.5: Impacto de ndices


Verifique o tempo de sua duplicao, mas um ndice composto.
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

DROP INDEX T8_IDX_01;


DROP INDEX T8_IDX_02;
CREATE INDEX T8_IDX_03 ON T8(OWNER,OBJECT_NAME);
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;
INSERT INTO T8 SELECT * FROM T7;
TRUNCATE TABLE T8;

161

Lab 7.6: Impacto de ndices


Verifique o uso dos ndices.
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

CONN SCOTT/TIGER
DROP INDEX T8_IDX_03;
INSERT INTO T8 SELECT * FROM T7;
CREATE INDEX T8_IDX_01 ON T8(OWNER);
CREATE INDEX T8_IDX_02 ON T8(OBJECT_NAME);
ALTER INDEX T8_IDX_01 MONITORING USAGE;
ALTER INDEX T8_IDX_02 MONITORING USAGE;

SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
FROM
'

COL INDEX_NAME FORMAT A40


SELECT INDEX_NAME, MONITORING, USED FROM V$OBJECT_USAGE;
SELECT COUNT(*) FROM T8 WHERE OWNER = 'SCOTT';
SELECT COUNT(*) FROM T8 WHERE OWNER = 'SYS';
SELECT COUNT(*) FROM T8 WHERE OWNER = 'SYSTEM';
SELECT INDEX_NAME, MONITORING, USED, START_MONITORING
V$OBJECT_USAGE;

162

Estatsticas

163

Estatsticas e SQL Engine


Optimizer Statistics
Table statistics
Number of rows
Number of blocks
Average row length
Column statistics
Number of distinct values (NDV) in column
Number of nulls in column
Data distribution (histogram)
Extended statistics
Index statistics
Number of leaf blocks
Average data blocks per Key
Levels
Index clustering factor

System Statistics
I/O performance and utilization
CPU performance and utilization

164

Estatsticas - Tabela
DBA_TABLES / ALL_TABLES / USER_TABLES

165

Estatsticas - ndices
DBA_INDEXES / ALL_INDEXES / USER_INDEXES

166

Estatsticas - Colunas
DBA_TAB_COLUMNS / ALL_TAB_COLUMNS / USER_TAB_COLUMNS

167

Estatsticas - Histogramas
DBA_TAB_COLUMNS / ALL_TAB_COLUMNS / USER_TAB_COLUMNS

DBA_TAB_HISTOGRAMS / ALL_TAB_HISTOGRAMS / USER_TAB_HISTOGRAMS

168

Histogramas
- Buckets: mximo de 255 (2048 12c);
- Frequency Histograms;
- Height-Balanced Histograms;
- Top Frequency Histograms (12c);
- Hybrid Histograms (12c).

http://docs.oracle.com/database/121/TGSQL/tgsql_histo.htm

169

Frequency Histograms
Utilizados se:
- Se o NDV menor ou igual que a quantidade de Buckets indicados na coleta;
- utilizado AUTO_SAMPLE_SIZE na execuo da coleta.

170

Height Balanced Histograms


Utilizados se:
- Se o nmero de Buckets indicados na coleta menor que o NDV.

171

Top Frequency Histograms (12c)


Utilizados se:
- Se o NDV maior que a quantidade de Buckets indicados na coleta;
- utilizado AUTO_SAMPLE_SIZE na execuo da coleta;
- Se o percentual de linhas ocupadas pelos Top Values igual ou maior que p, sendo
que p = (1-(1/Buckets))*100.

172

Hybrid Histograms (12c)


Utilizados se:
- Se o nmero de Buckets indicados na coleta menor que o NDV;
- utilizado AUTO_SAMPLE_SIZE na execuo da coleta;
- Se os crittios para Top Frequency Histograms no se aplicam.

173

Extended Statistics Column Groups

174

Extended Statistics Column Groups


SQL> CONN SH/SH
SQL> SELECT DBMS_STATS.CREATE_EXTENDED_STATS(USER, 'CUSTOMERS')
FROM DUAL;
SQL> BEGIN
DBMS_STATS.GATHER_TABLE_STATS( 'SH','CUSTOMERS',
METHOD_OPT=>'FOR ALL COLUMNS SIZE SKEWONLY ' || 'FOR COLUMNS SIZE
SKEWONLY (CUST_STATE_PROVINCE,COUNTRY_ID)');
END;
/
SQL> SELECT SYS.DBMS_STATS.SHOW_EXTENDED_STATS_NAME('SH','CUSTOMERS',
'(CUST_STATE_PROVINCE,COUNTRY_ID)') COL_GROUP_NAME
FROM DUAL;
SQL> SELECT EXTENSION_NAME, EXTENSION FROM USER_STAT_EXTENSIONS
WHERE TABLE_NAME='CUSTOMERS';

175

175

Extended Statistics Expression

176

Extended Statistics Expression


SQL> CONN SH/SH
SQL> SELECT DBMS_STATS.CREATE_EXTENDED_STATS(USER, 'CUSTOMERS')
FROM DUAL;
SQL> BEGIN
DBMS_STATS.GATHER_TABLE_STATS('SH','CUSTOMERS'
,METHOD_OPT => 'FOR ALL COLUMNS SIZE SKEWONLY FOR COLUMNS
(LOWER(CUST_STATE_PROVINCE)) SIZE SKEWONLY');
END;
/

177

177

Coleta de Estatsticas - ANALYZE


ANALYZE TABLE emp VALIDATE STRUCTURE;
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE;
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE FAST;
ANALYZE TABLE emp VALIDATE STRUCTURE CASCADE ONLINE;
UTLCHAIN.SQL / UTLCHN1.SQL
ANALYZE TABLE emp LIST CHAINED ROWS INTO CHAINED_ROWS;

178

OPTIMIZER_DYNAMIC_SAMPLING

179

OPTIMIZER_DYNAMIC_SAMPLING

180

Estatsticas: Coleta Automtica


Automatic Optimizer Statistics Collection
SQL> SELECT CLIENT_NAME, STATUS FROM DBA_AUTOTASK_CLIENT;
SQL> BEGIN
DBMS_AUTO_TASK_ADMIN.DISABLE (
CLIENT_NAME => 'AUTO OPTIMIZER STATS COLLECTION'
,OPERATION
=> NULL
,WINDOW_NAME => NULL
);
END;
/
SQL> BEGIN
DBMS_AUTO_TASK_ADMIN.ENABLE (
CLIENT_NAME => 'AUTO OPTIMIZER STATS COLLECTION'
,OPERATION
=> NULL
,WINDOW_NAME => NULL
);
END;
/

181

Estatsticas: Coleta Manual


Procedures para coleta
DBMS_STATS.GATHER_DATABASE_STATS
DBMS_STATS.GATHER_SCHEMA_STATS
DBMS_STATS.GATHER_TABLE_STATS
DBMS_STATS.GATHER_INDEX_STATS

182

182

Estatsticas: Opes de Coleta


ESTIMATE_PERCENT (Percentual ou DBMS_STATS.AUTO_SAMPLE_SIZE)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10);
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE);
DEGREE (Quantidade ou DBMS_STATS.DEFAULT_DEGREE)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2);
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>DBMS_STATS.DEFAULT_DEGREE);
CASCADE (TRUE, FALSE, ou AUTO_CASCADE)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>TRUE);
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE);

183

183

Estatsticas: Opes de Coleta


OPTIONS (GATHER, GATHER_STALE, GATHER_EMPTY, GATHER_AUTO)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>TRUE,
OPTIONS=>'GATHER_STALE');
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO);
GRANULARITY (ALL, AUTO, DEFAULT, GLOBAL, GLOBAL AND PARTITION,
PARTITION, SUBPARTITION)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO, GRANULARITY=ALL);
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO, GRANULARITY=AUTO);

184

184

Estatsticas: Opes de Coleta


NO_INVALIDATE (TRUE, FALSE, ou DBMS_STATS.AUTO_INVALIDATE)
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO, GRANULARITY=AUTO, NO_INVALIDATE=TRUE);
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => 10, DEGREE=>2, CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO, GRANULARITY=AUTO,
NO_INVALIDATE='DBMS_STATS.AUTO_INVALIDATE');

185

185

Estatsticas: Opes de Coleta


METHOD_OPT
FOR ALL COLUMNS SIZE 100
FOR ALL COLUMNS SIZE AUTO
FOR ALL COLUMNS SIZE REPEAT
FOR ALL COLUMNS SIZE SKEWONLY
FOR ALL INDEXED COLUMNS SIZE 100
FOR ALL INDEXED COLUMNS SIZE AUTO
FOR ALL INDEXED COLUMNS SIZE REPEAT
FOR ALL INDEXED COLUMNS SIZE SKEWONLY
FOR COLUMNS C1 SIZE 100
FOR COLUMNS C1 SIZE AUTO
FOR COLUMNS C1 SIZE REPEAT
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE,
METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO');

186

186

Estatsticas: Opes de Coleta


Coleta geral
EXEC DBMS_STATS.GATHER_DATABASE_STATS
(ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE,
DEGREE=>2,
CASCADE=>AUTO_CASCADE
OPTIONS=>'GATHER_AUTO,
GRANULARITY=>AUTO,
NO_INVALIDATE=>'DBMS_STATS.AUTO_INVALIDATE',
METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE 1');

Coleta por exceo


EXEC DBMS_STATS.UNLOCK_TABLE_STATS('SCOTT','EMP');
EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT','EMP');
EXEC DBMS_STATS.GATHER_TABLE_STATS ('SCOTT', 'EMP',
ESTIMATE_PERCENT=>100, DEGREE=>1, CASCADE=>TRUE, OPTIONS=>'GATHER',
GRANULARITY=>'ALL',NO_INVALIDATE=>TRUE,METHOD_OPT=>'FOR ALL INDEXED
COLUMNS SIZE AUTO');
EXEC DBMS_STATS.LOCK_TABLE_STATS('SCOTT','EMP');

187

187

Estatsticas: Consulta
Tabela
SELECT TABLE_NAME, NUM_ROWS, BLOCKS, EMPTY_BLOCKS, AVG_SPACE,
CHAIN_CNT, AVG_ROW_LEN, SAMPLE_SIZE, LAST_ANALYZED FROM USER_TABLES
ORDER BY 1;
ndices
SELECT TABLE_NAME, INDEX_NAME, NUM_ROWS, BLEVEL, LEAF_BLOCKS,
DISTINCT_KEYS, CLUSTERING_FACTOR, AVG_LEAF_BLOCKS_PER_KEY,
AVG_DATA_BLOCKS_PER_KEY, SAMPLE_SIZE, LAST_ANALYZED FROM USER_INDEXES
ORDER BY 1,2;
Colunas
SELECT TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, NUM_NULLS, DENSITY,
LOW_VALUE, HIGH_VALUE, DATA_LENGTH, AVG_COL_LEN, SAMPLE_SIZE,
LAST_ANALYZED FROM USER_TAB_COLUMNS ORDER BY 1,2;
Histogramas
SELECT H.TABLE_NAME, H.COLUMN_NAME, C.HISTOGRAM, H.ENDPOINT_NUMBER,
H.ENDPOINT_ACTUAL_VALUE, H.ENDPOINT_REPEAT_COUNT FROM
USER_TAB_HISTOGRAMS H, USER_TAB_COLUMNS C WHERE H.TABLE_NAME =
C.TABLE_NAME AND H.COLUMN_NAME = C.COLUMN_NAME AND HISTOGRAM <> 'NONE'
ORDER BY 1,2,4;

188

Outras Estatsticas
Fixed Objects Statistics (V$SQL, V$SESSION, etc.)
SQL> EXEC DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;
Dictionary Statistics (DBA_SEGMENTS, DBA_TABLES, etc.);
SQL> EXEC DBMS_STATS.GATHER_DICTIONARY_STATS;

189

System Statistics
Consulta
SQL> SELECT PNAME, PVAL1 FROM SYS.AUX_STATS$;
Remoo
SQL> EXEC DBMS_STATS.DELETE_SYSTEM_STATS;
Coleta NOWORKLOAD
SQL> EXEC DBMS_STATS.GATHER_SYSTEM_STATS;
Coleta WORKLOAD
SQL> EXEC DBMS_STATS.GATHER_SYSTEM_STATS('START');
SQL> EXEC DBMS_STATS.GATHER_SYSTEM_STATS('STOP');

190

Lab 8.1: System Statistics


Verifique e guarde os planos de execuo do captulo de JOINs.
Colete as estatsticas de sistema durante uma carga, e verifique sua alterao.
SQL> SELECT PNAME, PVAL1 FROM SYS.AUX_STATS$;
SQL> EXEC DBMS_STATS.GATHER_SYSTEM_STATS('START');
$ cd /home/oracle/swingbench/bin/
$ ./charbench -uc 10 -cs //nerv01/ORCL
...
SQL> EXEC DBMS_STATS.GATHER_SYSTEM_STATS('STOP');
SQL> SELECT PNAME, PVAL1 FROM SYS.AUX_STATS$;

Verifique novamente os planos de execuo do captulo de JOINs.

191

Estatsticas Pendentes

192

Lab 8.2: Estatsticas Pendentes


Colete estatsticas, e verifique-as antes de publica-las.
SQL> CONN SH/SH
SQL> EXEC DBMS_STATS.SET_TABLE_PREFS
('SH','CUSTOMERS','PUBLISH','FALSE');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','CUSTOMERS');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;
SQL> EXEC DBMS_STATS.PUBLISH_PENDING_STATS('SH','CUSTOMERS');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;
SQL> EXEC DBMS_STATS.SET_TABLE_PREFS
('SH','SALES','PUBLISH','FALSE');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','SALES');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;
SQL> EXEC DBMS_STATS.DELETE_PENDING_STATS('SH','SALES');
SQL> SELECT * FROM USER_TAB_PENDING_STATS;

193

Restore de Estatsticas

194

Lab 8.3: Restore de Estatsticas


Execute o Restore de uma estatstica anterior.
SQL> CONN OE/OE
SQL> COL TABLE_NAME FORMAT A10
SQL> SELECT
TABLE_NAME,
TO_CHAR(STATS_UPDATE_TIME,'YYYY-MM-DD:HH24:MI:SS') AS
STATS_MOD_TIME
FROM
DBA_TAB_STATS_HISTORY
WHERE TABLE_NAME='ORDERS'
AND OWNER='OE'
ORDER BY STATS_UPDATE_TIME DESC;
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('OE', 'ORDERS');
SQL> EXEC DBMS_STATS.RESTORE_TABLE_STATS( 'OE','ORDERS',
TO_TIMESTAMP('2015-01-28:15:00:00','YYYY-MM-DD:HH24:MI:SS') );

195

Transporte de Estatsticas

196

Transporte de Estatsticas
Origem
EXEC DBMS_STATS.CREATE_STAT_TABLE (ownname => 'HR', stattab =>
TESTE_STATS'));
EXEC DBMS_STATS.GATHER_SCHEMA_STATS ('HR');
BEGIN DBMS_STATS.EXPORT_SCHEMA_STATS (ownname => 'HR', stattab =>
'TESTE_STATS'
$ expdp HR/HR DIRECTORY=dump_directory DUMPFILE=TESTE_STATS.dmp
TABLES=TESTE_STATS
Destino:
$ impdp PORTILHO DIRECTORY=dump_directory DUMPFILE=TESTE_STATS.dmp
TABLES=TESTE_STATS
SQL> EXEC DBMS_STATS.IMPORT_SCHEMA_STATS(ownname => 'HR', stattab =>
'TESTE_STATS');

197

Lab 8.4: Coleta de Estatsticas


Verifique os planos de execuo dos SQL abaixo.
SQL> CONN SCOTT/TIGER
SQL> SET AUTOTRACE ON EXPLAIN
SQL> SELECT ID, NAME FROM T1 WHERE ID =
SQL> SELECT ID, NAME FROM T2 WHERE ID =
SQL> SELECT ID, NAME FROM T1 WHERE ID <
SQL> SELECT ID, NAME FROM T2 WHERE ID <
SQL> SELECT ID, NAME FROM T1 WHERE ID <
SQL> SELECT ID, NAME FROM T2 WHERE ID <

1;
1;
5;
5;
10;
10;

Remova as estatsticas e verifique novamente os planos de execuo.


SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT','T1');
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT','T2');
Desabilite as estatsticas dinmicas, e verifique novamente os planos de execuo.
SQL> ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=0;
Colete as estatsticas com os parmetros padro, e verifique novamente os planos de
execuo.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','T1');
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','T2');

198

Lab 8.5: Coleta de Estatsticas


Verifique os planos de execuo dos SQL abaixo.
SQL> SELECT COUNT(OBJECT_TYPE), OBJECT_TYPE FROM T7 GROUP BY OBJECT_TYPE
ORDER BY 1;
SQL> CREATE INDEX IND_T7_01 ON T7(OBJECT_TYPE);
SQL> SET AUTOTRACE ON EXPLAIN
SQL> SELECT COUNT(OBJECT_NAME) FROM T7 WHERE OBJECT_TYPE = 'SYNONYM';
SQL> SELECT COUNT(OBJECT_NAME) FROM T7 WHERE OBJECT_TYPE = 'PACKAGE';
SQL> SELECT COUNT(OBJECT_NAME) FROM T7 WHERE OBJECT_TYPE = 'DIRECTORY';
Remova as estatsticas e verifique novamente os planos de execuo.
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT','T7');
Reabilite as estatsticas dinmicas, e verifique novamente os planos de execuo.
SQL> ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=2;
SQL> ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=11;
Colete as estatsticas com os parmetros padro, e verifique novamente os planos de
execuo.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','T7');
Colete as estatsticas com Histogramas incorretos para o NDV, e com o tamanho exato do
NDV, e verifique novamente os planos de execuo.

199

Modelagem

200

PKs: Surrogate or Natural?


Natural Keys (RG, CPF, Nota Fiscal, Matrcula, Aplice...)
Naturalidade no entendimento das colunas;
Reduo da largura da linha;
Menor quantidade de JOINs para exibir o resultado final;
Validao natural de regras de negcio.
Surrogate Keys (SEQUENCE, IDENTITY, MAX + 1 com FOR UPDATE)
Alteraes com menor impacto;
Reduo da largura das chaves;
Reduo da possibilidade de concorrncia em alteraes de campos;
Composio desnecessria;
Simplicidade de JOINs.

201

Lab 9.1: Data Types


Verifique os planos de execuo dos SQL abaixo.
SQL> CONN SCOTT/TIGER
SQL>
SQL>
SQL>
SQL>
SQL>

CREATE TABLE T91 (ID VARCHAR(255), NAME VARCHAR(255));


CREATE INDEX T91_IDX ON T91(ID);
CREATE INDEX T1_IDX ON T1(ID);
INSERT INTO T91 SELECT * FROM T1;
COMMIT;

SQL>
SQL>
SQL>
SQL>

SET AUTOTRACE ON
SELECT COUNT(*) FROM T1 WHERE ID=1;
SELECT COUNT(*) FROM T91 WHERE ID=1;
SELECT COUNT(*) FROM T91 WHERE ID='1';

202

Extrao de Planos de Execuo

203

Fontes de Planos de Execuo


- PLAN_TABLE, carregada por EXPLAIN PLAN / DBMS_XPLAN.DISPLAY ou
AUTOTRACE (e SQL Developer, Toad, etc.);
- VIEWs de planos compilados e armazenados na Library Cache;
- Tabelas de AWR / STATSPACK;
- Arquivos Trace (10046, 10053, etc.).

204

Explain Plan
Sintaxe:
EXPLAIN PLAN [SET STATEMENT_ID=id] [INTO table] FOR statement;
Exemplo:
SQL> EXPLAIN PLAN SET STATEMENT_ID='TESTE1' FOR
SELECT ENAME FROM EMP;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
Limitaes do Explain Plan:
- o Plano, no a Execuo;
- No utiliza Bind Peeking / ACS;
- Todas Variveis Bind so consideradas VARCHAR2;
- Depende do ambiente de execuo (trigger de logon?).

205

Views
Dynamic Performance Views:
- V$SQL_PLAN
- V$SQL_PLAN_STATISTICS
- V$SQL_WORKAREA
- V$SQL_PLAN_STATISTICS_ALL (V$SQL_PLAN_STATISTICS +
V$SQL_WORKAREA)
Chave < 10g: ADDRESS, HASH_VALUE, CHILD_HUMBER
Chave >= 10g: SQL_ID
Exemplo:
SQL> SELECT STATUS, SQL_ID, SQL_CHILD_NUMBER
FROM V$SESSION
WHERE USERNAME = 'SCOTT';
SQL> SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('a10jnjwd22gs8', 0));
SQL> SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('a10jnjwd22gs8'));

206

AWR
Tabelas:
- STATS$SQL_PLAN (STATSPACK)
- DBA_HIST_SQL_PLAN
- DBA_HIST_SQLTEXT
- DBA_HIST_SQLSTAT
- DBA_HIST_SQLBIND
Exemplo:
SQL> SELECT SQL_ID, SQL_TEXT
FROM DBA_HIST_SQLTEXT
WHERE SQL_TEXT LIKE '%SELECT ENAME FROM EMP%';
SQL> SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('a10jnjwd22gs8'));

Requer Licena Diagnostics Pack

207

AWR
SQL Statement
@$ORACLE_HOME/rdbms/admin/awrsqrpt.sql
Enter value for report_type: html
Enter value for num_days: 1
Enter value for begin_snap: 40
Enter value for end_snap: 41
Enter value for sql_id: 062savj8zgzut
Enter value for report_name: AWR_SQL_01.html
SQL Statement (Specific Database Instance)
@$ORACLE_HOME/rdbms/admin/awrsqrpi.sql

208

208

Execution Plan
SQL> CONN SCOTT/TIGER
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS('SCOTT','T7');
SQL> SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE
OBJECT_TYPE = 'SYNONYM';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT
OBJECT_TYPE
SQL> SELECT
OBJECT_TYPE

/*+ GATHER_PLAN_STATISTICS */ COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE


= 'PACKAGE';
/*+ GATHER_PLAN_STATISTICS */ COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE
= 'DIRECTORY';

209

209

Execution Plan
SQL> CONN SCOTT/TIGER
SQL> EXEC DBMS_STATS.DELETE_SCHEMA_STATS(USER);
SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO
AND DEPT.DEPTNO IN (10);
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO
AND DEPT.DEPTNO IN (10,20);
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT /*+ GATHER_PLAN_STATISTICS */ EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO AND DEPT.DEPTNO IN (10);
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT /*+ GATHER_PLAN_STATISTICS */ EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO AND DEPT.DEPTNO IN (10,20);
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT /*+ GATHER_PLAN_STATISTICS */ EMPNO, ENAME, DNAME, LOC FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

210

210

Execution Plan

211

211

Execution Plan
SQL> CONN / AS SYSDBA
SQL> ALTER SYSTEM SET STATISTICS_LEVEL=ALL;
SQL>
SQL>
SQL>
SQL>

CONN SCOTT/TIGER
ALTER SESSION SET STATISTICS_LEVEL=ALL;
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'SYNONYM';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'PACKAGE';


SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'DIRECTORY';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

212

212

Execution Plan
SQL> CONN SCOTT/TIGER
SQL> COL SQL_TEXT FORMAT A150
SQL> SELECT SQl_ID, CHILD_NUMBER, SQL_TEXT FROM V$SQL WHERE SQL_TEXT LIKE '%T7%';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('d43dypzv2mdyz', 0, 'ALLSTATS
LAST'));

213

213

Execution Plan

214

214

Execution Plan
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

CONN SCOTT/TIGER
ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING = 0;
EXEC DBMS_STATS.DELETE_TABLE_STATS(USER, 'T7');
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,

= 'TABLE';
'ALLSTATS LAST'));
= 'DIRECTORY';
'ALLSTATS LAST'));
= 'SYNONYM';
'ALLSTATS LAST'));

215

215

Execution Plan
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS(USER, 'T7');
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T7', ESTIMATE_PERCENT=>100,
METHOD_OPT=>'FOR ALL COLUMNS SIZE 1');
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'TABLE';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'DIRECTORY';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'SYNONYM';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

216

216

Execution Plan
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS(USER, 'T7');
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T7', ESTIMATE_PERCENT=>100,
METHOD_OPT=> 'FOR ALL COLUMNS SIZE 5');
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'TABLE';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'DIRECTORY';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
SQL> SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE = 'SYNONYM';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

217

217

Execution Plan
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

EXEC DBMS_STATS.DELETE_TABLE_STATS(USER, 'T7');


EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T7');
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,
SELECT COUNT(OBJECT_NAME) FROM SCOTT.T7 WHERE OBJECT_TYPE
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL,

= 'TABLE';
'ALLSTATS LAST'));
= 'DIRECTORY';
'ALLSTATS LAST'));
= 'SYNONYM';
'ALLSTATS LAST'));

218

218

Adaptive Plans

219

219

Lab 10.1: Adaptive Plans


Execute o SQL abaixo duas vezes, comparando o Plano Real de Execuo.
$ sqlplus OE/OE
SQL> SELECT o.order_id, v.product_name
FROM
orders o,
( SELECT order_id, product_name
FROM
order_items o, product_information p
WHERE p.product_id = o.product_id
AND
list_price < 50
AND
min_price < 40 ) v
WHERE o.order_id = v.order_id;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));
SQL> SELECT o.order_id, v.product_name
FROM
orders o,
( SELECT order_id, product_name
FROM
order_items o, product_information p
WHERE p.product_id = o.product_id
AND
list_price < 50
AND
min_price < 40 ) v
WHERE o.order_id = v.order_id;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));

220

Lab 10.2: Adaptive Plans


Verifique a diferena entre os dois Cursores.
SQL> SELECT CHILD_NUMBER, CPU_TIME, ELAPSED_TIME, BUFFER_GETS
FROM
V$SQL
WHERE SQL_ID = 'gm2npz344xqn8';
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('gm2npz344xqn8',0));
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('gm2npz344xqn8',1));

221

Lab 10.3: Adaptive Plans


Execute o SQL abaixo duas vezes, comparando o Plano Real de Execuo.
$ sqlplus OE/OE
EXPLAIN PLAN FOR
SELECT product_name FROM order_items o, product_information p
WHERE o.unit_price = 15
AND
quantity > 1
AND
p.product_id = o.product_id;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
SELECT product_name FROM order_items o, product_information p
WHERE o.unit_price = 15
AND
quantity > 1
AND
p.product_id = o.product_id;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS LAST'));
SELECT product_name FROM order_items o, product_information p
WHERE o.unit_price = 15
AND
quantity > 1
AND
p.product_id = o.product_id;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS LAST
+ADAPTIVE'));

222

Anlise de Planos de Execuo

223

Anlise de Plano

224

Anlise de Plano
- Stand-alone Operations: apenas uma operao filho;
- Unrelated-combine Operations: operaes filho so executadas de forma
independente;
AND-EQUAL, BITMAP AND, BITMAP MINUS, CONCATENATION, CONNECT BY
WITHOUT FILTERING, HASH JOIN, INTERSECTION, MERGE JOIN, MINUS,
MULTI_TABLE INSERT, SQL MODEL, TEMP TABLE TRANSFORMATION,
UNION-ALL.
- Related-combine Operations: a primeira operao filho executada apenas uma
vez, e controla a execuo das outras operaes filho, de forma intercalada;
NESTED LOOPS, UPDATE, CONNECT BY WITH FILTERING, BITMAP KEY
ITERATION;
- Blocking Operations (SORT)
- Nonblocking Operations (FILTER)

225

Stand-alone Operation

226

226

Stand-alone Operation - STOPKEY

227

227

Stand-alone Operation - STOPKEY

228

228

Stand-alone Operation - FILTER

229

229

Unrelated-combine Operation

230

230

Related-combine Operation

231

231

Lab 11.1: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN HR/HR
SQL> SELECT e.employee_id, j.job_title, e.salary, d.department_name
FROM employees e, jobs j, departments d
WHERE e.employee_id < 103
AND e.job_id = j.job_id
AND e.department_id = d.department_id;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR
(NULL, NULL, 'ALLSTATS LAST'));

232

Lab 11.2: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN SHSB/SHSB
SQL> SELECT *
FROM
(SELECT times.calendar_quarter_desc,
customers.cust_first_name,
customers.cust_last_name,
customers.cust_id,
SUM(sales.amount_sold),
rank() over(PARTITION BY times.calendar_quarter_desc
ORDER BY SUM(amount_sold) DESC) AS
rank_within_quarter
FROM sales,
customers,
times
WHERE sales.cust_id = customers.cust_id
AND times.calendar_quarter_desc = '2002-2'
AND times.time_id = sales.time_id
GROUP BY customers.cust_id,
customers.cust_first_name,
customers.cust_last_name,
customers.cust_id,
times.calendar_quarter_desc)
WHERE rank_within_quarter < 16;

233

Lab 11.3: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN SHSB/SHSB
SQL> SELECT channel_desc, calendar_week_number, countries.country_iso_code,
TO_CHAR(SUM(amount_sold), '9,999,999,999') SALES$
FROM sales, customers, times, channels, countries
WHERE sales.time_id=times.time_id AND sales.cust_id=customers.cust_id AND
sales.channel_id= channels.channel_id
AND customers.country_id = countries.country_id
AND channels.channel_desc IN
('Internet','Partners') AND times.calendar_year = '1998'
AND times.calendar_week_number IN ('23','24')
AND countries.country_iso_code IN ('ES','FR')
GROUP BY CUBE(channel_desc, calendar_week_number, countries.country_iso_code);
SQL> SELECT channel_desc, calendar_week_number, countries.country_iso_code,
TO_CHAR(SUM(amount_sold), '9,999,999,999') SALES$
FROM sales, customers, times, channels, countries
WHERE sales.time_id=times.time_id AND sales.cust_id=customers.cust_id AND
sales.channel_id= channels.channel_id
AND customers.country_id = countries.country_id
AND channels.channel_desc IN
('Internet','Partners') AND times.calendar_year = '2010'
AND times.calendar_week_number IN ('37','38')
AND countries.country_iso_code IN ('US','ZA')
GROUP BY CUBE(channel_desc, calendar_week_number, countries.country_iso_code);

234

Lab 11.4: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN SHSB/SHSB
SQL> SELECT SUM(amount_sold),
t.calendar_month_desc,
t.calendar_week_number,
c.country_name
FROM sales s,
times t,
countries c,
customers cu
WHERE s.time_id
= t.time_id
AND t.calendar_month_desc = '2010-11'
AND cu.country_id
= c.country_id
AND s.cust_id
= cu.cust_id
AND c.country_iso_code = 'DK'
group by t.calendar_month_desc,
t.calendar_week_number,
c.country_name;

235

Lab 11.5: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN SHSB/SHSB
SQL> SELECT t.time_id,
to_char(SUM(amount_sold),
'9,999,999,999') AS sales,
to_char(AVG(SUM(amount_sold)) over(ORDER BY t.time_id range BETWEEN INTERVAL '2'
DAY preceding AND INTERVAL '2' DAY following),
'9,999,999,999') AS
centered_5_day_avg
FROM sales s,
times t
WHERE t.calendar_month_desc IN('1996-01','1996-02','1996-03','1996-04')
AND s.time_id = t.time_id
GROUP BY t.time_id
ORDER BY t.time_id;
SQL> SELECT t.time_id,
to_char(SUM(amount_sold),
'9,999,999,999') AS sales,
to_char(AVG(SUM(amount_sold)) over(ORDER BY t.time_id range BETWEEN INTERVAL '2'
DAY preceding AND INTERVAL '2' DAY following),
'9,999,999,999') AS
centered_5_day_avg
FROM sales s,
times t
WHERE t.calendar_month_desc IN('2007-10','2007-11','2007-12','2008-01')
AND s.time_id = t.time_id
GROUP BY t.time_id
ORDER BY t.time_id;

236

Lab 11.6: Anlise de Plano


Execute o SQL abaixo e analise seu plano de execuo.
SQL> CONN SHSB/SHSB
SQL> WITH v AS
(SELECT p.Prod_Name Product_Name,
t.Calendar_Year YEAR,
t.Calendar_Week_Number Week,
SUM(Amount_Sold) Sales
FROM Sales s,
Times t,
Products p
WHERE s.Time_id
= t.Time_id
AND s.Prod_id
= p.Prod_id
AND p.Prod_name
IN ('Envoy External Keyboard')
and T.CALENDAR_YEAR IN (2003,2004)
AND t.Calendar_Week_Number = 21
GROUP BY p.Prod_Name,
t.Calendar_Year,
t.Calendar_Week_Number
)
...

237

Lab 11.7: Anlise de Plano


...
SELECT Product_Name Prod,
YEAR,
Week,
Sales,
Weekly_ytd_sales,
Weekly_ytd_sales_prior_year
FROM
(SELECT --Start of year_over_year sales
Product_Name,
YEAR,
Week,
Sales,
Weekly_ytd_sales,
LAG(Weekly_ytd_sales, 1) OVER (PARTITION BY Product_Name, Week ORDER BY YEAR)
Weekly_ytd_sales_prior_year
FROM
...

238

Lab 11.8: Anlise de Plano


...
(SELECT -- Start of dense_sales
v.Product_Name Product_Name,
t.Year YEAR,
t.Week Week,
NVL(v.Sales,0) Sales,
SUM(NVL(v.Sales,0)) OVER (PARTITION BY v.Product_Name, t.Year ORDER BY
t.week) weekly_ytd_sales
FROM v PARTITION BY (v.Product_Name)
RIGHT OUTER JOIN
(SELECT DISTINCT Calendar_Week_Number Week,
Calendar_Year YEAR
FROM Times
WHERE Calendar_Year IN (2003,2004)
) t
ON (v.week = t.week
AND v.Year = t.Year)
) dense_sales
) year_over_year_sales
where year = 2004
AND WEEK = 21
ORDER BY 1,2,3;

Execute novamente os SQLs do SHSB e analise os planos, mas com o usurio


SHSBP.

239

Estabilidade de Plano

240

Evoluo de Shared SQL


- Bind Variable
- CURSOR_SHARING
- Bind Variable Peeking (9i)
- Extended Cursor Sharing / Adaptive Cursor Sharing (11gR1)
- Cardinality Feedback (11gR2)
- Adaptive Optimizer / Automatic Reoptimization / Adaptive Plan (12cR1)

241

Estabilidade do Plano
HINTs (Session: _OPTIMIZER_IGNORE_HINTS = TRUE)

Parmetros de Controle do CBO

Parmetros ocultos de Controle do CBO

Stored Outlines

SQL Profiles (DBA_SQL_PROFILES)

SQL Plan Baselines

242

Baselines

243

Baselines
Consulta:
DBA_SQL_PLAN_BASELINES
Carregar Baselines Automaticamente:
SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE;
SQL> ALTER SYSTEM SET OPTIMIZER_USE_SQL_PLAN_BASELINES=TRUE;
Carregar Baselines manualmente:
SQL> EXEC DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(ATTRIBUTE_NAME=>'SQL
TEXT', ATTRIBUTE_VALUE=>'%SELECT ID, NAME FROM T1%')
SQL> EXEC DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(SQL_ID=>'1234567890',
PLAN_HASH_VALUE=>'ABCDEFGH');
Remover Baselines:
SQL> EXEC
DBMS_SPM.DROP_SQL_PLAN_BASELINE(SQL_HANDLE=>'SYS_SQL_1234567890');

244

Baselines
SQL> CONN / AS SYSDBA
SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE;
SQL> ALTER SYSTEM SET OPTIMIZER_USE_SQL_PLAN_BASELINES=TRUE;
SQL>
SQL>
SQL>
SQL>
FROM

CONN SCOTT/TIGER
CREATE TABLE T AS SELECT * FROM ALL_OBJECTS;
SELECT COUNT(DISTINCT(OWNER)) FROM T;
SELECT SQL_TEXT, SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED
DBA_SQL_PLAN_BASELINES;

SQL> CREATE BITMAP INDEX T_INDEX_01 ON T(OWNER);


SQL> SELECT COUNT(DISTINCT(OWNER)) FROM T;
SQL> SELECT SQL_TEXT, SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED
FROM DBA_SQL_PLAN_BASELINES;

245

Ferramentas Avanadas

246

Lab 12.1: SQLT - Instalao


MOS Doc ID 215187.1: SQLT Diagnostic Tool
Execute a instalao do SQLT.
$ unzip sqlt.zip
$ cd sqlt/install
$ sqlplus / AS SYSDBA
SQL> @install
<ENTER>
Nerv2015 <ENTER>
Nerv2015 <ENTER>
USERS <ENTER>
TEMP <ENTER>
SCOTT <ENTER>
T <ENTER>
SQL>
SQL>
SQL>
SQL>
SQL>

GRANT
GRANT
GRANT
GRANT
GRANT

SQLT_USER_ROLE
SQLT_USER_ROLE
SQLT_USER_ROLE
SQLT_USER_ROLE
SQLT_USER_ROLE

TO
TO
TO
TO
TO

OE;
SH;
SHSB;
SHSBP;
HR;

247

Lab 12.2: SQLTXPLAIN - Extrao


Verifique os SQL_ID dos SQL executados pelos dois SCHEMAS.
SQL> SELECT SQL_ID, SQL_TEXT FROM V$SQL WHERE
PARSING_SCHEMA_NAME = 'SHSB';
SQL> SELECT * FROM DBA_HIST_SQLTEXT WHERE SQL_ID IN (SELECT
SQL_ID FROM DBA_HIST_SQL_PLAN WHERE OBJECT_OWNER = 'SHSBP');
Extraia o Relatrio SQL dos SQL_ID executados pelos dois SCHEMAS.
$ sqlplus / AS SYSDBA
@$ORACLE_HOME/rdbms/admin/awrsqrpt.sql
Extraia o Relatrio SQLT dos SQL_ID executados pelos dois SCHEMAS.
$ cd sqlt/run
$ sqlplus SHSB/SHSB
SQL> @sqltxtract 2jb7w23a4ad72
Nerv2015 <ENTER>
$ unzip sqlt_s36985_xtract_grgrdq5ja4a1x.zip
$ firefox sqlt_s36985_main.html

248

SQLHC

MOS Doc ID 1366133.1: SQL Tuning Health-Check Script (SQLHC)


Verificaes:
- CBO Object Statistics
- CBO Parameters
- CBO System Statistics
- CBO Data Dictionary Statistics
- CBO Fixed-objects Statistics

249

Lab 12.3: SQLHC


Extraia o SQLHC dos SQLs analizados pelo SQLT.
$ cd /home/oracle
$ unzip sqlhc.zip
$ cd sqlhc
$ sqlplus SYSTEM/Nerv2015
SQL> @sqlhc.sql T 2jb7w23a4ad72

250

DBMS_SQLTUNE

251

Lab 12.4: DBMS_SQLTUNE


Execute o SQL_TUNE nos SQLs analizados pelo SQLT.
SQL> CONN / AS SYSDBa
SQL> DECLARE RET_VAL VARCHAR2(4000);
BEGIN
RET_VAL := DBMS_SQLTUNE.CREATE_TUNING_TASK(SQL_ID => '2hr53jd1gg9u2', SCOPE
=> DBMS_SQLTUNE.SCOPE_COMPREHENSIVE, TIME_LIMIT => 60, TASK_NAME => 'Portilho
Tuning Task', DESCRIPTION => 'Portilho Tuning Task');
END;
/
SQL> EXEC DBMS_SQLTUNE.EXECUTE_TUNING_TASK('Portilho Tuning Task');
SQL>
SQL>
SQL>
FROM

SET LONG 9000


SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('Portilho Tuning Task') FROM DUAL;
SELECT DBMS_SQLTUNE.SCRIPT_TUNING_TASK('Portilho Tuning Task') RECOMMENTATION
DUAL;

Remova o SQL_TUNE executado, aps executar a correo.


SQL> EXEC DBMS_SQLTUNE.DROP_TUNING_TASK('Portilho Tuning Task');

252

Rows x Sets

253

Rows x Sets
Isto no representa uma tabela!

254

Rows x Sets
Quais os empregados que passaram a mesma quantidade de anos em cada cargo ocupado?
Mtodo procedural:
- Listar todos os empregados;
- Listas todos os cargos, data inicial e final destes empregados, calculando a quantidade de anos;
- Armazenar estes dados em formato temporrio;
- Para cada empregado, verificar se todos as quantidades de anos so iguais;
- Descartar os empregados que no possuem todas as quantidade de anos iguais.
Mtodo por conjunto:
SELECT EMPLOYEE_ID
FROM JOB_HISTORY
GROUP BY EMPLOYEE_ID
HAVING
MIN(ROUND(MONTHS_BETWEEN(START_DATE, END_DATE) / 12,0)) =
MAX(ROUND(MONTHS_BETWEEN(START_DATE, END_DATE) / 12,0)

255

Rows x Sets
Qual a quantidade mdia de dias entre os pedidos de um cliente?
Mtodo procedural:
- Liste todos os pedidos do cliente X;
- Selecione os pedidos e suas datas;
- Para cada pedido, selecione a data do pedido anterior;
- Calcule qual a quantidade de dias entre a data do pedido e a data anterior;
- Calcule a mdia destas quantidades.
Mtodo por conjunto:
SELECT
(MAX(TRUNC(ORDER_DATE)) - MIN(TRUNC(ORDER_DATE))) / COUNT(ORDER_ID)
FROM ORDERS
WHERE CUSTOMER_ID = 102 ;

256

Rows x Sets
Crie uma tabela com os clientes pequenos, outra com os clientes mdios, e outra com os
clientes grandes.
Mtodo procedural:
- Selecionar os clientes que compraram menos de 10000;
- Inseri-los na tabela SMALL_CUSTOMERS;
- Selecionar os clientes que compraram entre 10000 e 99999;
- Inseri-los na tabela MEDIUM_CUSTOMERS;
- Selecionar os clientes que compraram mais de 100000;
- Inseri-los na tabela LARGE_CUSTOMERS;
Mtodo por conjunto:
INSERT ALL
WHEN SUM_ORDERS < 10000 THEN INTO SMALL_CUSTOMERS
WHEN SUM_ORDERS >= 10000 AND SUM_ORDERS < 100000 THEN INTO
MEDIUM_CUSTOMERS
ELSE INTO LARGE_CUSTOMERS
SELECT CUSTOMER_ID, SUM(ORDER_TOTAL) SUM_ORDERS
FROM OE.ORDERS
GROUP BY CUSTOMER_ID;

257

Rows x Sets

Altere o bnus para 20% de quem candidato mas ainda no tem bnus, remova de quem
ganha mais de 7.500, e marque como 10% o bnus de quem ainda no candidato mas recebe
menos que 7.500.
Mtodo procedural:
- Selecione os empregados que devem receber a alterao de 20%;
- Faa a alterao dos empregados que devem receber a alterao de 20%;
- Selecione os empregados que devem receber a alterao de 10%;
- Faa a alterao dos empregados que devem receber a alterao de 10%;
- Selecione os empregados que no devem mais ser candidatos a bnus;
- Remova os empregados que no devem mais ser candidatos a bnus.
Mtodo por conjunto:
MERGE INTO BONUS_DEPT60 B
USING (SELECT EMPLOYEE_ID, SALARY, DEPARTMENT_ID
FROM EMPLOYEES WHERE DEPARTMENT_ID = 60) E
ON (B.EMPLOYEE_ID = E.EMPLOYEE_ID)
WHEN MATCHED THEN
UPDATE SET BONUS = E.SALARY * 0.2 WHERE B.BONUS = 0
DELETE WHERE (E.SALARY > 7500)
WHEN NOT MATCHED THEN
INSERT (B.EMPLOYEE_ID, B.BONUS)
VALUES (E.EMPLOYEE_ID, E.SALARY * 0.1)
WHERE (E.SALARY < 7500);

258

Otimizaes

259

Lab 13.1: Append e Redo


Crie uma tabela de testes, e execute uma gravao, com parmetros diferentes.
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T131 AS SELECT * FROM ALL_OBJECTS WHERE 1=0;
SQL>
SQL>
SQL>
SQL>

SET AUTOTRACE TRACEONLY


INSERT INTO T131 SELECT
INSERT INTO T131 SELECT
INSERT INTO T131 SELECT

STATISTICS
* FROM ALL_OBJECTS;
* FROM ALL_OBJECTS;
* FROM ALL_OBJECTS;

SQL> INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;


SQL> INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;

O que aconteceu?

SQL> INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;


SQL>
SQL>
SQL>
SQL>

ALTER TABLE T131 NOLOGGING;


INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;
INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;
INSERT /*+ APPEND */ INTO T131 SELECT * FROM ALL_OBJECTS;

Qual a diferena exibida pelo SET AUTOTRACE TRACEONLY STATISTICS?

260

Paralelismo
Permite Query, DML e DDL.
Quantos processos de paralelismo utilizar?
Um objeto pode ter Parallel permanente, independente do SQL:
SQL> ALTER TABLE SCOTT.T PARALLEL 4;
O Parallel SQL pode ser utilizado diretamente no SQL:
SQL> SELECT /*+ PARALLEL(T2 4) */ COUNT(*) FROM T2;
SQL> SELECT /*+ PARALLEL(T2 4,2) */ COUNT(*) FROM T2;

261

Paralelismo
Parmetros:
PARALLEL_MIN_SERVERS = Nmero entre 0 e PARALLEL_MAX_SERVERS.
PARALLEL_MAX_SERVERS = De 0 a 3600.
PARALLEL_MIN_PERCENT = De 0 a 100.
PARALLEL_DEGREE_POLICY = MANUAL, LIMITED ou AUTO.
PARALLEL_MIN_TIME_THRESHOLD = AUTO | Segundos.
PARALLEL_ADAPTIVE_MULTI_USER = true ou false.
PARALLEL_DEGREE_LIMIT = CPU, IO ou Nmero.
PARALLEL_SERVERS_TARGET = Nmero entre 0 e PARALLEL_MAX_SERVERS.
PARALLEL_THREADS_PER_CPU = Qualquer nmero.
PARALLEL_EXECUTION_MESSAGE_SIZE = De 2148 a 32768
PARALLEL_FORCE_LOCAL = true ou false.
PARALLEL_INSTANCE_GROUP = Oracle RAC service_name ou group_name.
PARALLEL_AUTOMATIC_TUNING: Deprecated.
PARALLEL_IO_CAP_ENABLED = Deprecated.

262

Paralelismo
SQL> SELECT SID, SERIAL#, QCSID, QCSERIAL# FROM V$PX_SESSION;
SID
SERIAL#
QCSID QCSERIAL#
---------- ---------- ---------- ---------202
5249
12
387
20
3587
12
387
75
4043
12
387
141
233
12
387
204
751
12
387
16
229
12
387
73
3279
12
387
137
403
12
387
203
1137
12
387
18
103
12
387
79
5
12
387
134
3431
12
387
206
5
12
387
19
5
12
387
76
31
12
387
140
5
12
387
12
387
12

263

Lab 13.2: Paralelismo


Abra a sesso com o SCOTT com SET TIMING ON.
Em seguida, faa o teste do PARALLEL.
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T132 AS SELECT * FROM ALL_OBJECTS;
SQL> INSERT INTO T132 SELECT * FROM T132;
SQL> INSERT INTO T132 SELECT * FROM T132;
SQL> INSERT INTO T132 SELECT * FROM T132;
SQL> INSERT INTO T132 SELECT * FROM T132;
SQL> COMMIT;
Repita a operao com PARALLEL, e compare.
SQL> SET TIMING ON
SQL> SELECT COUNT(*) FROM T132;
SQL> SELECT /*+ PARALLEL(T132 4) */ COUNT(*) FROM T132;
SQL> SELECT /*+ PARALLEL(T132 20) */ COUNT(*) FROM T132;
SQL> SELECT /*+ PARALLEL(T132 40) */ COUNT(*) FROM T132;
Qual a diferena exibida pelo SET TIMING ON?

264

Lab 13.3: RESULT_CACHE


Execute o teste do RESULT_CACHE.
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T133 AS SELECT * FROM ALL_OBJECTS;
SQL> INSERT INTO T133 SELECT * FROM T133;
SQL> INSERT INTO T133 SELECT * FROM T133;
SQL> INSERT INTO T133 SELECT * FROM T133;
SQL> INSERT INTO T133 SELECT * FROM T133;
SQL> COMMIT;
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>
SQL>

SET TIMING ON
SET AUTOTRACE ON
SELECT COUNT(*) FROM T133;
SELECT COUNT(*) FROM T133;
SELECT COUNT(*) FROM T133;
SELECT /*+ RESULT_CACHE */ COUNT(*) FROM T133;
SELECT /*+ RESULT_CACHE */ COUNT(*) FROM T133;
SELECT /*+ RESULT_CACHE */ COUNT(*) FROM T133;

SQL> DELETE FROM T133 WHERE ROWNUM = 1;


SQL> SELECT /*+ RESULT_CACHE */ COUNT(*) FROM T133;

265

Compression
10g OLAP

11g OLTP

12c InMemory

266

Lab 13.4: Compression


Execute o teste do COMPRESSION.
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T134 AS SELECT * FROM ALL_OBJECTS;
SQL> INSERT INTO T134 SELECT * FROM T134;
SQL> INSERT INTO T134 SELECT * FROM T134;
SQL> INSERT INTO T134 SELECT * FROM T134;
SQL> INSERT INTO T134 SELECT * FROM T134;
SQL> INSERT INTO T134 SELECT * FROM T134;
SQL> COMMIT;
SQL>
SQL>
SQL>
SQL>

SET TIMING ON
SELECT COUNT(*) FROM T134;
SELECT COUNT(*) FROM T134;
SELECT COUNT(*) FROM T134;

SQL> ALTER TABLE T134 COMPRESS;


SQL> ALTER TABLE T134 MOVE;
SQL> SELECT COUNT(*) FROM T134;
SQL> SELECT COUNT(*) FROM T134;
SQL> SELECT COUNT(*) FROM T134;

267

Lab 13.5: CTAS


Execute o teste de DELETE x CTAS (CREATE TABLE AS SELECT).
SQL> CONN SCOTT/TIGER
SQL> CREATE TABLE T135 AS SELECT * FROM ALL_OBJECTS;
SQL> INSERT INTO T135 SELECT * FROM T135;
SQL> INSERT INTO T135 SELECT * FROM T135;
SQL> INSERT INTO T135 SELECT * FROM T135;
SQL> INSERT INTO T135 SELECT * FROM T135;
SQL> COMMIT;
SQL> SELECT COUNT(*) FROM T135;
SQL> SELECT COUNT(*) FROM T135 WHERE OBJECT_TYPE = 'SYNONYM';
SQL> SET TIMING ON
SQL> DELETE FROM T135 WHERE OBJECT_TYPE = 'SYNONYM';
SQL> ROLLBACK;
SQL> CREATE TABLE T135TEMP AS SELECT * FROM T135 WHERE
OBJECT_TYPE != 'SYNONYM';
SQL> DROP TABLE T135;
SQL> ALTER TABLE T135TEMP RENAME TO T135;

268

SQL: Melhores Prticas

269

Melhores Prticas
Menos mais.
Prefira SQL (MERGE?), se lhe atender.

Evite trocar entre PL/SQL e SQL (context switch).

Evite acesso desnecessrio a DUAL (operaes aritmticas, SEQUENCEs).

Troque UTL_FILE por EXTERNAL TABLES.

Utilize variveis BIND em SQLs repetitivos.

Variveis BINDs impedem SQL Injection.

No utilize Binds se o tempo total de compilao no for relevante quanto ao tempo


total de resposta.

A maneira mais rpida de se fazer um grande UPDATE / DELETE no fazer.

Evite Row-by-Row.

Evite Nested Row-by-Row.

Evite WHERE CAMPO LIKE 'A%' em colunas de baixa seletividade.

Evite mais ainda WHERE CAMPO LIKE '%A%'.

Evite o abuso de VIEWs, TRIGGERs, DBLINKs.

270

Você também pode gostar