Академический Документы
Профессиональный Документы
Культура Документы
ndice Introduo.......................................................................................................................3 1. Mtodo de Acesso......................................................................................................4 1.1 Full Table Scan.....................................................................................................4 1.2 Table Access by Rowid........................................................................................4 1.3 Index Scan............................................................................................................5 2. Tipos de Join..............................................................................................................8 2.1 Nested Loops........................................................................................................8 2.2 Sort-Merge...........................................................................................................9 2.3 Hash Join............................................................................................................10 2.5 Star Join..............................................................................................................11 2.6 Star transformation.............................................................................................12 3. Hints.........................................................................................................................14 3.1 Tipo de Otimizador............................................................................................14 3.2 Subquery / View.................................................................................................14 3.3 Acesso................................................................................................................15 3.4 Join.....................................................................................................................16 3.5 Parallel Query (PQ)............................................................................................17 3.7 Variados.............................................................................................................17 4. Dicas.........................................................................................................................18 4.1 Evitar funo em coluna indexada.....................................................................19 4.2 Join com colunas do mesmo tipo.......................................................................20 4.3 Coletar as estatsticas com regularidade.............................................................22 4.4 Sql Trace ...........................................................................................................24
Introduo
Este documento tem o objetivo de auxiliar os desenvolvedores e dbas na otimizao de consultas. Inicialmente revisaremos alguns pontos importantes: os mtodos de acesso, os algoritmos usados para realizao do join e os hints usados para modificar o plano de execuo das consultas. Em seguida veremos algumas dicas para se aproveitar o mximo da eficincia deste banco de dados.
1. Mtodo de Acesso
Representa o tipo de acesso para obter os dados de determinada tabela. O Oracle possui os seguintes mtodos: uma
Possui os seguintes tipos: Unique Scan: usado quando a tabela possui uma chave nica ou primria. Retorna apenas 1 rowid.
OPERATION ------------------------0 SELECT STATEMENT 1 TABLE ACCESS 2 INDEX OPTIONS OBJECT_NAME -------------------- ------------------. BY INDEX ROWID TESTE.TAB_LOC UNIQUE SCAN TESTE.TAB_LOC_PK
Range Scan: usado para obter um determinado intervalo de dados. Retorna 0 ou mais rowids.
OPERATION ------------------------0 SELECT STATEMENT 1 TABLE ACCESS 2 INDEX OPTIONS OBJECT_NAME -------------------- -------------------. BY INDEX ROWID TESTE.TAB_LOC RANGE SCAN TESTE.TAB_LOC_DATA
Full Scan: usado quando a query usa pelo menos uma coluna do ndice. Tambm usado quando a consulta no possui predicado e se deseja evitar a operao de sort.
Fast Full Scan: um Full Table Scan alternativo usado quando o ndice possui todas colunas necessrias para a query. Para ler todos dados do ndice, mais rpido que o Index Scan por possibilitar o Multiblock I/O e a paralelizao. Obs: no pode ser usado para evitar a operao de sort (os dados no so retornados de forma ordenada).
OPERATION OPTIONS ------------------------- -------------------0 SELECT STATEMENT 1 INDEX FAST FULL SCAN OBJECT_NAME ------------------. TESTE.TAB_LOC_DATA
Index Join: um hash join com alguns ndices da tabela. Juntos obtm todas colunas referenciadas na query.
OPERATION ------------------------0 SELECT STATEMENT 1 VIEW 2 HASH JOIN 3 INDEX 4 INDEX OPTIONS OBJECT_NAME ----------------- ----------------------. TESTE.index$_join$_001 . FAST FULL SCAN TESTE.TAB_LOC_DATA FAST FULL SCAN TESTE.TAB_LOC_PK
Bitmap: utiliza um bitmap como chave para cada valor distinto da coluna e uma funo de mapeamento que converte cada bit para um rowid. Se a coluna indexada tiver baixa cardinalidade, so rpidos e ocupam pouco espao. Obs: uma coluna considerada de baixa cardinalidade se o nmero de valores distintos for menor ou igual a 1% do total de registros.
OPERATION ------------------------0 SELECT STATEMENT 1 TABLE ACCESS 2 BITMAP CONVERSION 3 BITMAP INDEX OPTIONS OBJECT_NAME -------------------- -------------------. BY INDEX ROWID TESTE.VENDAS TO ROWIDS . SINGLE VALUE TESTE.VENDAS_TIPO_BM
2. Tipos de Join
O join uma operao que permite combinar o resultado de duas ou mais tabelas baseando se nos valores das colunas em comum. O Oracle utiliza os seguintes algoritmos
select * from tab_loc l, tab_loc_peq p where l.codigo = p.codigo; OPERATION ------------------------0 SELECT STATEMENT 1 NESTED LOOPS 2 TABLE ACCESS 3 TABLE ACCESS 4 INDEX OPTIONS OBJECT_NAME -------------------- -----------------. . FULL TESTE.TAB_LOC_PEQ BY INDEX ROWID TESTE.TAB_LOC UNIQUE SCAN TESTE.TAB_LOC_PK
2.2 Sort-Merge
Os registros de cada tabela so ordenados pelas colunas do join condition feito um merge das duas ordenaes e os registros que satisfizerem o join condition so retornados
select /*+ use_merge(l p) */ * from tab_loc l, tab_loc_peq p where l.codigo = p.codigo; OPERATION OPTIONS OBJECT_NAME ------------------------- -------------------- ---------------------0 SELECT STATEMENT . 1 MERGE JOIN . 2 TABLE ACCESS BY INDEX ROWID TESTE.TAB_LOC_PEQ 3 INDEX FULL SCAN TESTE.TAB_LOC_PEQ_PK 4 SORT JOIN . 5 TABLE ACCESS FULL TESTE.TAB_LOC
Obs: a etapa 2 no precisou realizar o sort porque o range scan j retornou os dados ordenados.
select /*+ use_hash(l) */ * from tab_loc l, tab_loc_peq p where l.codigo = p.codigo; OPERATION ------------------------0 SELECT STATEMENT 1 HASH JOIN 2 TABLE ACCESS 3 TABLE ACCESS OPTIONS OBJECT_NAME -------------------- -------------------. . FULL TESTE.TAB_LOC_PEQ FULL TESTE.TAB_LOC
Transformao 1 parte: obteno do result set SELECT ... FROM sales WHERE store_key IN (SELECT store_key FROM store WHERE sales_district IN ('WEST','SOUTHWEST')) AND time_key IN (SELECT time_key FROM time WHERE quarter IN ('3Q96', '4Q96', '1Q97')) AND product_key IN (SELECT product_key FROM product WHERE department = 'GROCERY'); 2 parte: join entre o result set e as dimenses
Plano de execuo SELECT STATEMENT HASH JOIN HASH JOIN HASH JOIN TABLE ACCESS SALES BY INDEX ROWID BITMAP CONVERSION TO ROWIDS BITMAP AND BITMAP MERGE BITMAP KEY ITERATION TABLE ACCESS STORE FULL BITMAP INDEX SALES_STORE_KEY RANGE SCAN BITMAP MERGE BITMAP KEY ITERATION TABLE ACCESS TIME FULL BITMAP INDEX SALES_TIME_KEY RANGE SCAN BITMAP MERGE BITMAP KEY ITERATION TABLE ACCESS PRODUCTS FULL BITMAP INDEX SALES_PRODUCT_KEY RANGE SCAN TABLE ACCESS TIME FULL TABLE ACCESS PRODUCTS FULL TABLE ACCESS STORE FULL
3. Hints
Hint um comentrio padronizado que se inclui no meio do comando para modificar o plano de execuo. Geralmente ele utilizado nos casos em que o Oracle no consegue definir uma boa estratgia. Sintaxe: select /*+ Hint... */ colunas ... from tabelas ... Abaixo segue a listagem dos hints para consultas:
Hash_Aj transforma o NOT IN subquery em hash anti-join Merge_Sj - transforma o EXISTS em sort-merge semi-join mantendo a semntica. O default do EXISTS usar o algoritmo nested loops. Obs: nos casos em que a tabela que est sendo verificada (tabela dentro do EXISTS) no possuir ndice nas colunas do join, haver um ganho de performance se o sort-merge semijoin for usado. Hash_Sj transforma o EXISTS em hash semi-join mantendo a semntica. O default do EXISTS usar o algoritmo nested loops. Obs: nos casos em que a tabela que est sendo verificada (tabela dentro do EXISTS) no possuir ndice nas colunas do join, haver um ganho de performance se o hash semi-join for usado. Push_Join_Pred(v) fora a view usar o join predicate da query principal
3.3 Acesso
Full(tab) fora o full table scan para tabela tab Cache(tab) fora que blocos retornados da consulta sejam colocados na lista LRU do buffer cache quando o full table scan for executado, se o tamanho da tabela for menor ou igual ao valor do parmetro CACHE_SIZE_THRESHOLD.
Nocache(tab) fora que os blocos retornados da consulta no sejam colocados na cache, mesmo que a tabela tenha o parmetro cache habilitado. Rowid(tab) fora o acesso a tabela tab pelo rowid Index(tab index) fora o acesso a tabela tab pelo ndice index Index_Asc(tab index) induz o Oracle a acessar o ndice index da tabela tab com um range scan Index_Desc(tab index) induz o Oracle a acessar o ndice index da tabela tab na ordem decrescente Ndex_Ffs(tab index) opta pelo fast full scan ao invs do full table scan Index_Combine(tab i1.. i5) realiza a combinao booleana de ndices bitmap com melhor custo. Index_join(tab i1.. i5) induz a utilizao index join And_Equal(tab i1.. i5) realiza o merge de 2 a 5 ndices com apenas 1 coluna. Use_Concat transforma a combinao de ORs/IN na clusula WHERE em uma query composta com operador de conjunto UNION ALL. No_Expand no permite a concatenao Driving_Site(tab) a query executada no site que a tabela tab se encontra
3.4 Join
Use_Nl(tab) induz o Oracle a optar a tabela tab como sendo a inner table. Use_Merge(tab) induz o Oracle a realizar o join da tabela tab com o mtodo sort-merge. Use_Hash(tab) induz o Oracle a realizar o join da tabela tab com o mtodo hash join. Star induz o Oracle a realizar o start query Star_Transformation induz o Oracle a optar pelo melhor plano com Star Transformation. A transformao s realizada se for benfico. Ordered induz o Oracle a executar o join na ordem em que as tabelas se encontram na clusula FROM (da esquerda para direita e de cima para baixo).
Pq_Distribute(tab,out,in)indica como distribuir os registros da tabela tab em uma PQ entre produtores e consumidores. Os valors para out (outer table) e in (inner table) podem ser: hash, none, broadcast ou partition. Noparallel(tab) evita a paralelizao do acesso a tabela tab Noparallel_Index(tab) evita o parallel index scan
3.7 Variados
Rewrite(v1[,v2]) permite que uma query compatvel com a consulta de uma materialized view (v1,v2,...) seja reescrita de forma que aproveite os dados pr processados da materialized view. Obs: verso posterior a 8.1 Norewrite no permite que a query seja reescrita
4. Dicas
Abaixo seguem as tabelas que usaremos nos exemplos.
tab_loc: tabela local ndices : tab_loc_pk (codigo) tab_loc_ind (data ) registros: 500.000 SQL> desc tab_loc Name -----------------------CODIGO DESCRICAO DATA VALOR Null? -------NOT NULL NOT NULL NOT NULL NOT NULL Type -------------VARCHAR2(10) VARCHAR2(50) DATE NUMBER
tab_loc_peq: tabela local pequena ndices : tab_loc_peq_pk (codigo) registros: 50 SQL> desc tab_loc_peq Name -----------------------CODIGO DESCRICAO DATA VALOR Null? -------NOT NULL NOT NULL NOT NULL NOT NULL Type -------------VARCHAR2(10) VARCHAR2(50) DATE NUMBER
tab_loc_gra: tabela local grande ndices : tab_loc_gra_pk (codigo) registros: 3.070.307 SQL> desc tab_loc_peq Name -----------------------CODIGO DESCRICAO DATA VALOR Null? -------NOT NULL NOT NULL NOT NULL NOT NULL Type -------------NUMBER(10) VARCHAR2(50) DATE NUMBER
tab_rem@link_bci: tabela remota ndices : tab_rem_pk (codigo) registros: 500.000 SQL> desc tab_rem@link_bci Name Null? ------------------------ -------CODIGO NOT NULL DESCRICAO NOT NULL DATA NOT NULL VALOR NOT NULL Type -----------VARCHAR2(10) VARCHAR2(50) DATE NUMBER
Statistics --------------------------------------------------0 recursive calls 6 db block gets 1196 consistent gets 1196 physical reads 0 redo size 205 bytes sent via SQL*Net to client 261 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed
Consulta eficiente select count(*) from tab_loc where data >= to_date(10/10/2003,dd/mm/yyyy) and data < to_date(10/10/2003,dd/mm/yyyy) + 1; Resultado Tempo: 0,1s
OPERATION -----------------------------0 SELECT STATEMENT 1 SORT 2 INDEX OPTIONS OBJECT_NAME -------------------- -----------------. AGGREGATE . RANGE SCAN TESTE.TAB_LOC_DATA
Statistics --------------------------------------------------0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 205 bytes sent via SQL*Net to client 310 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed
select count(*) from tab_loc l, tab_loc_gra g where l.codigo = g.codigo /* l.codigo VARCHAR2 e g.codigo NUMBER */ and g.data = to_date('10/10/2003','dd/mm/yyyy');
Resultado Tempo: 1s
OPERATION -----------------------------0 SELECT STATEMENT 1 HASH JOIN 2 TABLE ACCESS 3 INDEX 4 TABLE ACCESS OPTIONS OBJECT_NAME -------------------- ---------------------. . BY INDEX ROWID TESTE.TAB_LOC_GRA RANGE SCAN TESTE.TAB_LOC_GRA_DATA FULL TESTE.TAB_LOC
Statistics --------------------------------------------------0 recursive calls 4 db block gets 1061 consistent gets 0 physical reads 0 redo size 207 bytes sent via SQL*Net to client 378 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
Incluso da converso explcita de tipo select count(*) from tab_loc_gra g, tab_loc l where l.codigo = to_char(g.codigo,'fm99999999') /* ambos VARCHAR2 */ and g.data = to_date('10/10/2003','dd/mm/yyyy'); Resultado Tempo: 0,4s Obs: Apenas incluindo a converso de tipo, o tempo foi reduzido pela metade. Note que o plano de execuo no foi alterado.
OPERATION -----------------------------0 SELECT STATEMENT 1 SORT 2 HASH JOIN 3 TABLE ACCESS 4 INDEX 5 INDEX
OPTIONS OBJECT_NAME -------------------- ----------------------. AGGREGATE . . BY INDEX ROWID TESTE.TAB_LOC_GRA RANGE SCAN TESTE.TAB_LOC_GRA_DATA FAST FULL SCAN TESTE.TAB_LOC_PK
Statistics ----------------------------------------------------0 recursive calls 4 db block gets 1061 consistent gets 0 physical reads 0 redo size 206 bytes sent via SQL*Net to client 360 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
select /*+ ordered use_nl(l) */ count(*) from tab_loc_gra g, tab_loc l where l.codigo = to_char(g.codigo,'fm9999999') /* ambos c/ tipo VARCHAR2 */ and g.data = to_date('10/10/2003','dd/mm/yyyy');
Resultado Tempo: 0,01s OPERATION ---------------------------0 SELECT STATEMENT 1 SORT 2 NESTED LOOPS 3 TABLE ACCESS 4 INDEX 5 INDEX OPTIONS OBJECT_NAME -------------------- -------------------. AGGREGATE . . BY INDEX ROWID TESTE.TAB_LOC_GRA RANGE SCAN TESTE.TAB_LOC_GRA_DATA UNIQUE SCAN TESTE.TAB_LOC_PK
Statistics --------------------------------------------------0 recursive calls 0 db block gets 39 consistent gets 0 physical reads 0 redo size 206 bytes sent via SQL*Net to client 407 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
select l.* from tab_loc l, tab_loc_peq d, tab_rem@link_bci r where l.codigo = r.codigo and l.codigo = d.codigo
ID OTHER -- -----------------------------------------------------------------------3 SELECT "CODIGO" FROM "TAB_REM" "R" Statistics ----------------------------------------------------7 recursive calls 6 db block gets 1999953 consistent gets 0 physical reads 172 redo size 191 bytes sent via SQL*Net to client 332 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
Consulta com analyze analyze table tab_loc compute statistics; analyze table tab_loc_peq compute statistics;
select l.* from tab_loc l, tab_loc_peq d, tab_rem@link_bci r where l.codigo = r.codigo and l.codigo = d.codigo;
ID OTHER -- ---------------------------------------------------------------------6 SELECT "CODIGO" FROM "TAB_REM" "R" WHERE :1="CODIGO" Statistics ---------------------------------------------------0 recursive calls 0 db block gets 151 consistent gets 0 physical reads 0 redo size 207 bytes sent via SQL*Net to client 332 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
4) Desative o timed_statistics
alter system set timed_statistics=false;
5) Localize o trace gerado (sempre no servidor) o Os traces sero gerados no diretrio definido para o parmetro USER_DUMP_DEST. Para identific-lo execute:
select value from v$parameter where name = 'user_dump_dest';
O nome do comando:
arquivo
pode
ser
obtido
com
sguinte
select 'ora_'||spid||'_'||lower(i.instance_name)||'.trc' arquivo from v$process p, v$session s, v$instance i where p.addr = s.paddr and s.sid = <sid>;
Exemplo: formatar o trace de forma que os comandos estejam ordenados pelo tempo gasto no fetch. tkprof ora_33_mig.trc saida.txt explain=usr/usr sys=no sort=fchela