Sie sind auf Seite 1von 55

Melhoria de Consultas

Fatos
Questes Preliminares
Otimizao por Custo e Regra
Gerando Estatsticas
Package DBMS_STATS
Gerando Estatsticas com OEM
Hints
Senso Comum em SQL
Driving Table
Uso Eficiente de Clusulas Where No Indexadas
Usando ROWID
Reduzindo o Nmero de Acessos ao Banco
Usando DECODE
Cuidados na Clusula WHERE
Dicas
Casos Especiais

1. Fatos
Alguns fatos sobre melhoria de performance em consultas:
Melhoras no tempo de resposta so possveis atravs da tentativa e erro;
fundamental estudar e conhecer o projeto do seu banco de dados;
Durante o tunning possvel degradar a performance, ao invs de melhor-la;
importante isolar o problema, identificando as consultas SQL.

2. Questes Preliminares
Algumas questes surgem:
Quando algo realmente demorado?
A consulta est sendo executada em volumes reais de produo?
Est sendo realmente usado o plano de acesso gerado pelo otimizador?
Existem eventos ou mudanas no banco de dados que podem afetar a performance?

3. Otimizao por Custo e Regra


Regra:
Seu comportamento previsvel, pois sua anlise governada por 20 possveis
condies que podem existir em um comando SQL, ranqueando-as para definio do plano
de acesso.

Custo:
Seu comportamento orientado pelas informaes estatsticas disponveis sobre os
objetos envolvidos, bem como o dicionrio de dados. O otimizador define o plano de
acesso, que pode ser modificado manualmente com o uso do hints.

4. Gerando Estatsticas
Conhecido como CBO (Cost Based Optimizer), o otimizador o responsvel pela gerao
dos planos de acesso para a execuo das consultas.
Ele depende de estatsticas precisas sobre os objetos existentes no banco. Ele precisa
conhecer detalhadamente os objetos existentes no banco de dados, para gerar planos de
acesso eficientes.
Para isto ele estabelece um ranque baseado no critrio de menor custo, determinado pelo
consumo de I/O, memria e CPU.
Estatsticas podem ser geradas atravs da package DBMS_STATS.

4. Gerando Estatsticas (continuao)


O processo de gerao das estatsticas pode ser custoso, dependendo do tamanho da
tabela.
Sempre escolha a opo de coletar todas as estatsticas de uma tabela, mesmo que esta
operao no possa ser executada com a frequncia desejada.
Para grandes tabelas, possvel estabelecer um percentual de leitura para gerar
estatsticas por amostragem. A recomendao de que seja utilizado, no mnimo, 5% do
tamanho da tabela.
Para verificar quando uma tabela teve suas estatsticas computadas, use:
SQL> SELECT table_name, last_analyzed FROM dba_tables;
TABLE_NAME
LAST_ANALYZED
------------------------------------------TEST1
07/08/2005
TEST2
07/08/2005
TEST3
07/08/2005
...
SQL>

possvel fazer o mesmo para ndices, utilizando a view DBA_INDEXES.

5. Package DBMS_STATS
A package DBMS_STATS possui diversas procedures para realizar a coleta de estatstica
em diferentes nveis. As opes so as seguintes:
GATHER_DATABASE_STATISTICS
Gera estatstica para todos os objetos do banco.
GATHER_SCHEMA_STATISTICS
Gera estatstica para um schema.
GATHER_TABLE_STATISTICS
Gera estatstica para uma tabela e seus ndices.
GATHER_INDEX_STATISTICS
Gera estatstica para um ndice.

5. Package DBMS_STATS (continuao)


Exemplos:
Schema
SQL> EXECUTE DBMS_STATS.GATHER_SCHEMA_STATS (ownname => 'admin');
PL/SQL procedure successfully completed.
SQL>

Tabela
SQL> EXECUTE DBMS_STATS.GATHER_TABLE_STATS ('admin','cliente');
PL/SQL procedure successfully completed.
SQL>

Banco de dados
SQL> EXECUTE dbms_stats.gather_database_stats (> ESTIMATE_PERCENT => NULL, > METHOD_OPT => 'AUTO', > GRANULARITY => 'ALL', > CASCADE => 'TRUE',> OPTIONS => 'GATHER AUTO');
PL/SQL procedure successfully completed.
SQL>

5. Package DBMS_STATS (continuao)


Parmetros:
ESTIMATE_PERCENT: Percentagem de linhas que sero usadas para estimar as
estatsticas. NULL significa que a coleta ser em todas as linhas.
METHOD_OPT: Indica os diversos mtodos de coleta. AUTO significa que sero coletados
histogramas baseados na distribuio dos dados para as colunas referenciadas.
GRANULARITY: Somente para tabelas. ALL significa coletar estatsticas para parties,
subparties e estatsticas globais.
CASCADE: YES especifica que a estatstica de ndices ser coletada junto com a da tabela.
OPTIONS: Controla o processo de coleta das estatsticas:
GATHER: Inclui todos os objetos, sem exceo;
GATHER_AUTO: Inclui somente os objetos que o Oracle julgar necessrio;
GATHER_EMPTY: Inclui somente os objetos que no possuem estatstica.

6. Gerando Estatsticas com OEM


possvel gerar as estatsticas tambm via interface grfica do OEM (Oracle Enterprise
Manager). Para isto ser necessrio:
1) Na pgina principal, em Database, clicar em Servidor;
2) No grupo Query Optimization, clicar em Manage Optimizer Statistics;
3) Clicar em Gather Statistics.

7. Hints
possvel realizar tunning de uma consulta manualmente, atravs do uso de hints. Com ele
possvel sobrepor as decises do otimizador, definindo como deve ser a estratgia de
execuo da consulta.
Colocando os hints (dicas) de otimizao como comentrios em um comando SQL, ele
forado a seguir o plano que voc definiu, ao invs de utilizar o que foi definido pelo
otimizador.
Seu uso:
SELECT /*+ texto do hint */ .....
UPDATE /*+ texto do hint */ ....
DELETE /*+ texto do hint */ .....

Ex.:

SELECT /*+ RULE */


FROM empregado, depto
WHERE .

7. Hints (continuao)
Por que hints podem ser ignorados?
1) Escrita errada
2) Hint inapropriado
SELECT /*+ index(dept dpt_pk) */
FROM emp
WHERE emp_no = 12345
3) Conflito
SELECT /*+ index(emp dpt_idx) */
FROM emp
WHERE emp_no = 12345

tabela errada

ndice errado, no por emp_no

4) Identificao invlida de tabela


SELECT /*+ index(emp emp_pk) */
FROM emp E
WHERE E.emp_no = 12345

nome da tabela inapropriado

7. Hints (continuao)
Hints mais utilizados:
INDEX
Usado para forar a utilizao de um ou mais ndices no plano de acesso gerado pelo
otimizador.
Sintaxe:
select /*+ INDEX (table index1, index2) */ column1,

Exemplo:
select /*+ INDEX (emp deptno_idx) */ empno, ename, deptno
from emp
where deptno = 1;
select /*+ INDEX (emp deptno_idx, empno_idx) */ empno, ename, deptno
from emp
where deptno = 1
and empno = 7750;

7. Hints (continuao)
ORDERED
Determina a ordem de acesso que deve ser observada para acesso as tabelas
especificadas na clusula FROM.
Sintaxe:
select /*+ ORDERED */ column1,

Exemplo:
select /*+ ORDERED */ emp.empno, ename, dept.deptno, itemno
from emp, dept, orders
where emp.deptno = dept.deptno
and emp.empno = orders.empno
and dept.deptno = 1
and emp.empno = 7747
and orders.ordno = 45;

7. Hints (continuao)
FIRST_ROWS
O otimizador ir escolher o plano de acesso que retore mais rapidamente a quantidade de
linhas especificadas.
A consulta no pode ser do tipo INSERT, UPDATE ou DELETE. Seu uso tambm
ignorado quando se usa GROUP BY, DISTINCT, INTERSECT, MINUS e UNION.
Sintaxe:
select /*+ FIRST_ROWS(n) */ column1,

Exemplo:
select /*+ FIRST_ROWS */ empno, ename, deptno
from emp
where deptno = 1;
select /*+ FIRST_ROWS(10) */ empno, ename, deptno
from emp
where deptno = 1;

7. Hints (continuao)
FULL
Faz com que o otimizador execute um full table scan na tabela especificada.
Sintaxe:
select /*+ FULL(table) */ column1,

Exemplo:
select /*+ FULL(emp) */ empno, ename, deptno
from emp
where deptno = 1;

7. Hints (continuao)
NO_INDEX
Impede que o otimizador utilize um determinado ndice.
Sintaxe:
select /*+ NO_INDEX (table index1, index2) */ column1,

Exemplo:
select /*+ NO_INDEX (emp deptno_idx) */ ename, deptno
from emp
where deptno = 1;

7. Hints (continuao)
USE_NL
USE_NL (use nested loops) a forma mais rpida de retornar uma linha, levando em
considerao o tempo de resposta. Ele pega a linha de uma tabela (que atende a condio
requerida) e junta (join) com o resultado de uma segunda tabela.
Sintaxe:
select /*+ USE_NL (table1, table2,) */ column1,

Exemplo:
select /*+ ORDERED USE_NL(dept) */ empno, ename, dept.deptno
from emp, dept
where emp.deptno = dept.deptno
and dept.deptno = 1
and emp.empno = 7747;

7. Hints (continuao)
USE_HASH
a forma mais rpida de fazer join entre muitas linhas de mltiplas tabelas, se houver
memria suficiente para suportar a operao. Parecido com o USE_NL, com a excesso de
colocar toda a segunda tabela na memria.
Os parmetros de inicializao HASH_AREA_SIZE e PGA_AGGREGATE_TARGET
precisam ser dimensionados apropriadamente para suportar estas operaes, seno ela
ocorrer em disco.
Sintaxe:
select /*+ USE_HASH (table1, table2,...) */ column1,

Exemplo:
select /*+ USE_HASH (dept) */ empno, ename, dept.deptno
from emp, dept
where emp.deptno = dept.deptno
and emp.empno = 7747;

7. Hints (continuao)
PARALLEL
Faz o otimizador quebrar a consulta em pequenos pedaos (degree) e processar cada uma
com um diferente server process. Uma consulta que realize operaes de sort ir utilizar o
dobro de server process especificados.
Sintaxe:
/*+ PARALLEL (table, DEGREE) */
degree o nmero de pedaos em que a consulta ser quebrada.
Se no for especificado, ser utilizado o valor default definido na criao da tabela.

Exemplo:
select /*+ PARALLEL (order_line_items) */ invoice_number, invoice_date
from order_line_items
order by invoice_date;
select /*+ PARALLEL (order_line_items, 4) */ invoice_number, invoice_date
from order_line_items
order by invoice_date;

7. Hints (continuao)
APPEND
Aumenta a performance de comandos de INSERT, mas com o potencial custo em termos de
espao.
Ele no verifica se h espao livre nos blocos j utilizados pela tabela, inserindo dados
somente em blocos novos. Espao acaba sendo desperdiado, mas a execuo do
comando se torna mais rpida.
Se uma tabela nunca sofre excluso de linhas, este hint deve ser utilizado.
Sintaxe:
insert /*+ APPEND */

Exemplo:
insert /*+ APPEND */
into emp (empno, deptno)
values (7747, 10);

8. Senso Comum em SQL

SQL uma linguagem muito flexvel. possvel escrever um comando em diferentes


formas, gerando os mesmos resultados.
Algumas pessoas acreditam que, enquanto um comando SQL retornar os dados desejados,
ele estar correto. Este entendimento errado.
Um comando SQL s estar correto se produzir o resultado esperado no mais curto espao
de tempo possvel, sem causar impacto de performance nos recursos disponveis.
As tcnicas envolvidas em melhoria de consultas nada mais so do que a aplicao de
regras de senso comum. A experincia e a exercitao iro contribuir para o seu
aprendizado.

9. Driving Table
O objetivo em qualquer comando SQL minimizar o nmero de leituras a disco que
precisam ser feitas.
Geralmente os comandos SQL possuem mais de uma tabela relacionada na clusula
FROM. Uma delas ser a primeira a ser acessada. A ela chamamos de driving table.
Fazendo a escolha correta, ganhos de performance podem ser alcanados. Para defini-la,
coloque-a como a ltima tabela da clusula FROM.
Ex.: TAB1: 16.384 linhas
TAB2:
1 linha
SELECT COUNT(*) FROM TAB1, TAB2
SELECT COUNT(*) FROM TAB2, TAB1

0,96s para executar


26,09s para executar

9. Driving Table (continuao)


Passos feitos pelo Oracle:
1) Scan e sort na primeira tabela (driving table);
2) Scan na segunda tabela;
3) Merge das linhas obtidas nas duas consultas.
16.384 linhas sero lidas e ordenadas. possvel que esta operao consuma o espao de
memria alocado para cada usurio (parmetro SORT_AREA_SIZE). Consequentemente a
operao de sort ser feita em pequenos pedaos e armazenados temporariamente em
disco (temporary file).
Ao termino, ser feito o merge com os dados da segunda tabela, produzindo ento o
resultado.

10. Uso Eficiente de Clusulas Where No Indexadas


A avaliao das equaes que no utilizam ndices, ligadas pela expresso AND, so
avaliadas de forma botton-up (de baixo para cima).
Isto significa que a primeira clusula (ltima na lista AND) avaliada, e se for verdadeira, a
segunda clusula ento ser testada. Sempre deve ser colocada a expresso mais
custosa no incio da clusula WHERE.
Ex.: Gerentes que ganham > US$ 50.000,00 e possuem + de 25 pessoas em seu staff
SELECT .....
156 segundos
FROM emp E
WHERE emp_salary > 50.000
AND
emp_type = MANAGER
AND
25 < (SELECT COUNT(*) FROM emp WHERE emp_mgr = E.emp_no)

SELECT .....
10,6 segundos
FROM emp E
WHERE 25 < (SELECT COUNT(*) FROM emp WHERE emp_mgr = E.emp_no)
AND
emp_salary > 50.000
AND
emp_type = MANAGER

11. Usando ROWID


O ROWID de uma linha a forma mais rpida de acess-la. Ele uma chave codificada
que representa o nmero fsico do registro em um bloco de dados do banco.
Ganhos de performance podem ser alcanados quando um registro selecionado para
posterior alterao. O ROWID pode ser includo na clusula SELECT. Isto ir permitir, na
hora da atualizao, o acesso mais eficiente possvel.
SELECT ROWID, .....
INTO :emp_rowid, .....
FROM emp
WHERE emp_no = 56722
FOR UPDATE;
UPDATE emp
SET name = ..
WHERE ROWID = :emp_rowid;

12. Reduzindo o Nmero de Acessos ao Banco


Sempre que uma consulta executada, uma srie de passos internos ao banco so
realizados. So eles: PARSE, EXECUTE e FETCH.
Quanto maior a reduo no nmero de acessos ao banco, maior ser a performance. Isto
particularmente benfico em aplicaes cliente-servidor, quando o banco de dados est
sendo acessado via rede.

Cenrio 1 (2 cursores, 2 fetchs):


SELECT emp_name, salary, grade
FROM emp
WHERE emp_no = 342;
SELECT emp_name, salary, grade
FROM emp
WHERE emp_no = 291;

12. Reduzindo o Nmero de Acessos ao Banco (continuao)


Cenrio 2 (1 cursor, 2 fetchs)
DECLARE
CURSOR C1 IS (e_no number) IS
SELECT emp_name, salary, grade FROM emp WHERE emp_no = e_no;
BEGIN
OPEN C1(342);
FETCH C1 INTO ....;
......
OPEN C1 (291);
FETCH C1 INTO ....;
......
CLOSE C1;
END;
Cenrio 2 (1 cursor, 1 fetch)
SELECT A.emp_name, A.salary, A.grade,
B.emp_name, B.salary, B.grade
FROM emp A, emp B
WHERE A.emp_no = 342 and B.emp_no = 291;

13. Usando DECODE


Em consultas SQL podem ocorrer contas/somas de dados para um grupo de linhas, de
acordo com alguma condio estabelecida. A funo DECODE oferece uma forma eficiente
de realizar esta tarefa, reduzindo a carga de processamento.

Cenrio 1
SELECT COUNT(*), SUM(salary) FROM emp
WHERE dept_no = 20 and emp_name LIKE SMITH%;
SELECT COUNT(*), SUM(salary) FROM emp
WHERE dept_no = 30 and emp_name LIKE SMITH%

Cenrio 2
SELECT COUNT(DECODE(dept_no, 20, X, NULL)) D20_COUNT,
COUNT(DECODE(dept_no, 30, X, NULL)) D30_COUNT,
SUM(DECODE(dept_no, 20, salary, NULL)) D20_SAL,
SUM(DECODE(dept_no, 30, salary, NULL)) D30_SAL
FROM emp WHERE emp_name LIKE SMITH%

14. Cuidados na Clusula WHERE


Existem algumas situaes na clusula WHERE onde o Oracle ir ignorar o uso de ndices.
Freqentemente estas clusulas podem ser reescritas, fornecendo a mesma resposta e
fazendo com que ndices existentes sejam utilizados.

Cenrio 1
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE SUBSTR(account_name,1,7) = CAPITAL;
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE account_name LIKE CAPITAL%;

14. Cuidados na Clusula WHERE (continuao)


Expresses com != ou <> desabilitam o uso de ndices. ndices somente nos dizem o
que h na tabela, no o contrrio.

Cenrio 2
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE amount != 0;
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE amount > 0;

14. Cuidados na Clusula WHERE (continuao)


O uso de TRUNC em um campo com data desabilita o uso de ndices.

Cenrio 3
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE trunc(trans_date) = TRUNC(sysdate);
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE trans_date between TRUNC(sysdate) and TRUNC(sysdate) + .99999;
Cuidado
SELECT TO_DATE(01/01/2010) + .99999 01/01/2010 23:59:59
SELECT TO_DATE(01/01/2010) + .999999 02/01/2010 00:00:00

14. Cuidados na Clusula WHERE (continuao)


O uso de concatenaes (||) tambm pode desabilitar o uso de ndices.

Cenrio 4
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE account_name || account_type = AMEXA;
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE account_name = AMEX
AND
account_type = A;

14. Cuidados na Clusula WHERE (continuao)


O uso de operadores aritmticos causa o mesmo efeito do uso de funes em campos
indexados. Eles desabilitam o uso de ndices.

Cenrio 5
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE amount + 3000 < 5000;
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE amount < 2000;

14. Cuidados na Clusula WHERE (continuao)


Colunas de uma tabela que aparecem como operadores nos dois lados de uma clusula no
utilizam ndices, resultando em um full table scan.

Cenrio 6
No use
SELECT account_name, trans_date, amount
FROM transaction
WHERE account_name = NVL(:acc_name, account_name);
Use
SELECT account_name, trans_date, amount
FROM transaction
WHERE account_name = NVL(:acc_name, %);

15. Dicas
Realizar tunning de um comando ou grupo de comandos SQL mais uma batalha do que
propriamente arte. Somente poucas pessoas conseguem fazer isto simplesmente por
instinto.
Somente a experincia e observao faro com que bons resultados sejam alcanados,
consolidando o conhecimento acerca deste assunto. necessrio ser persistente.
Sero vistas agoras algumas dicas para situaes que podem ocorrer no dia-a-dia do DBA.

15. Dicas (continuao)


Removendo Linhas Duplicadas
DELETE FROM emp E
WHERE E.rowid > (SELECT MIN(X.rowid)
FROM emp X
WHERE X.emp_no = E.emp_no)

Contando Linhas em uma Tabela


SELECT COUNT( ...coluna indexada...) FROM transaction;

mais rpida

SELECT COUNT( * ) FROM transaction;

5% mais lento

SELECT COUNT( 1 ) FROM transaction;

15 a 20% mais lento

15. Dicas (continuao)


Minimizando Subquerys (lookups) em uma Consulta

Evite
SELECT emp_name
FROM emp
WHERE emp_cat = (SELECT MAX(category) FROM emp_categories)
AND sal_range = (SELECT MAX(sal_range) FROM emp_categories)
AND emp_dept = 0020;
Use
SELECT emp_name
FROM emp
WHERE (emp_cat, sal_range) = (SELECT MAX(category), MAX(sal_range)
FROM emp_categories)
AND emp_dept = 0020;

15. Dicas (continuao)


Joins entre Tabelas ao invs de EXISTS
Quando o percentual de linhas retornadas na drive table for alto, considere o uso de joins.
Evite
SELECT emp_name
FROM emp E
WHERE EXISTS
(

SELECT X
FROM dept
WHERE dept_no = E.dept_no
AND dept_cat = A);

Use
SELECT emp_name
FROM emp E, dept D
WHERE E.dept_no = D.dept_no
AND
D.dept_cat = A

15. Dicas (continuao)


EXISTS no lugar de Joins entre Tabelas
Quando o percentual de linhas retornadas na drive table for baixo, passa a valer a pena o
uso de subquerys.
Evite
SELECT
FROM dept D, emp E
WHERE E.dept_no = D.dept_no
AND
E.emp_type = MANAGER
AND
D.dept_cat = A
Use
SELECT
FROM emp E
WHERE EXISTS ( SELECT X FROM dept
WHERE dept_no = E.dept_no
AND dept_cat = A)
AND
E.emp_type = MANAGER

15. Dicas (continuao)


NOT EXISTS no lugar de NOT IN
O uso de NOT IN em subquerys pode causar a realizao de sorts internos. O uso de
NOT EXISTS evita isto, aumentando sua performance.
Evite
SELECT
FROM emp
WHERE dept_no NOT IN

SELECT dept_no FROM dept


WHERE dept_cat = A);

Use
SELECT
FROM emp
WHERE NOT EXISTS

SELECT X
FROM dept
WHERE dept_no = E.dept_no
AND dept_cat = A);

15. Dicas (continuao)


UNION ALL no lugar do UNION
O uso de UNION fora com que as linhas retornadas em cada uma das consultas sofram
sort, merge e filter. Assim as linhas duplicadas sero removidas.
O uso de UNION ALL simplesmente retorna todas as linhas sem remover as duplicatas, no
sendo necessrias nenhuma das operaes acima.
A maioria dos comandos que utilizam UNION pode ser trocados por UNION ALL, pois foram
escritos de forma a no retornar linhas duplicadas.
SELECT acct_num, balance_amt
FROM debit_transactions
WHERE tran_date = 31-12-2009
UNION
SELECT acct_num, balance_amt
FROM credit_transactions
WHERE tran_date = 31-12-2009

SELECT acct_num, balance_amt


FROM debit_transactions
WHERE tran_date = 31-12-2009
UNION ALL
SELECT acct_num, balance_amt
FROM credit_transactions
WHERE tran_date = 31-12-2009

15. Dicas (continuao)


Uso de OR
A anlise destas expresses feita de forma top-down (de cima para baixo). As clusulas
indexadas mais restritivas devem vir primeiro, deixando as que retornam maior nmero de
linhas para o final da expresso. O sucesso na avaliao da primeira expresso evita a
avaliao das demais.
.....
WHERE key1 = 10
OR
key2 = 20

retorna menos linhas


retorna mais linhas

15. Dicas (continuao)


Busca por ndice ou Full Table Scan?
A escolha depende de inmeros fatores, alguns dos quais no se podemos exercer muito
controle:
- Tamanho de bloco no SO;
- Tamanho de bloco no Oracle;
- Tamanho da shared pool;
- Paralelismo (ex.: PARALLEL_MIN_SERVERS);
- Tamanho de leitura em table scan (ex.: DB_FILE_MULTIBLOCK_READ_COUNT);
- Tamanho da tabela;
- Tipo do sistema de arquivos (ex.: JFS, JFS2, RAW, etc);
- Subsistema de disco (ex.: RAID 0....RAID 5).
A opo por full table scan como melhor mtodo de leitura pode variar a performance de
10% a 50% na tabela lida.

15. Dicas (continuao)


Explicitamente Desabilitando ndices
Se dois ou mais ndices podem atender a uma determinada consulta, mas o escolhido pelo
otimizador no o desejado, possvel influenci-lo em sua escolha.
SELECT .....
FROM emp
WHERE emp_category = MANAGING DIRECTOR
AND
dept_no + 0 = 0010
-- concatenar desabilita o uso de ndices
AND
emp_type || = A

Ainda assim prefervel o uso de hints, pela clareza.


SELECT /*+ INDEX(EMP EMP_CAT_IDX) */ .....
FROM emp
WHERE emp_category = MANAGING DIRECTOR
AND
dept_no = 0010
AND
emp_type = A

15. Dicas (continuao)


Evitando o uso de colunas com NULL
Como null no pode ser utilizado em operaes e comparaes, evitar seu uso em algumas
circunstncias pode maximizar a performance em processos.
Em um cenrio hipottico, onde novas vendas entram com o campo new preenchido com
NULL, e precisam ser selecionadas:
Evite
SELECT ....
FROM Sales
WHERE new is NULL
Use
SELECT .
FROM sales
WHERE new = 0

-- Na tabela dever ser utilizado valor default para o campo e um


-- ndice para a realizao da consulta.

15. Dicas (continuao)


Problemas de Converso em Tipos em Colunas
Converso de datatypes sempre algo custoso e que traz srios problemas relacionados a
performance.
SELECT ....
FROM emp
WHERE emp_no = 123

-- emp_no um campo numrico

Nestas situaes um full table scan pode ocorrer. O problema pode ser pior se
considerarmos joins entre tabelas cujos campos possuem datatypes diferentes.
SELECT .....
FROM emp, sales
WHERE emp.emp_no = sales.emp_no

-- emp_no varchar na tabela Sales

15. Dicas (continuao)


Usando WHERE ao invs de ORDER BY
comum especificar a clusula ORDER BY quando, na realidade, ela pode ser evitada. Ela
sempre ir forar que todos os registros que atendam a clusula WHERE sofram sort, o
que demanda tempo.
muito mais eficiente obter as linhas via um ndice. possvel manipular uma consulta e
obter os dados na ordem necessria sem a necessidade de realizar sort atravs da
clusula ORDER BY.
Ao invs de
SELECT .. FROM department
ORDER BY dept_type
Pode ser usado
SELECT FROM department
WHERE dept_type > 0

-- deve existir um ndice por esta coluna

15. Dicas (continuao)


Ordenando via Hints
ndices provm um mecanismo fcil e eficiente de localizar linhas em uma tabela e,
conseqentemente, ordenar os dados. Com o advento do paralelismo no uso de querys a
Oracle passou a alertar sobre a possibilidade do uso de um ndice no hint no trazer os
dados de forma ordenada.
-- ordenando
SELECT /*+ INDEX(department dept_type_idx) */
FROM department
-- ordenando tambm, ascendentemente
SELECT /*+ INDEX_ASC(department dept_type_idx) */
FROM department
-- ordenando tambm, descendentemente
SELECT /*+ INDEX_DESC(department dept_type_idx) */
FROM department

16. Casos Especiais


Indexando colunas usadas tanto no SELECT quanto no WHERE
Full Table Scan (55 segundos)
SELECT ename FROM employees
WHERE dept_no = 10
-- sem ndice na coluna dept_no

Criando um ndice por DEPT_NO (7 segundos)


SELECT ename FROM employees
WHERE dept_no = 10
-- create index dept_idx1 on emproyee (dept_no)

Criando um ndice por DEPT_NO + ENAME (1 segundo)


SELECT ename FROM employees
WHERE dept_no = 10
-- create index dept_idx1 on emproyee (dept_no, ename)

16. Casos Especiais (continuao)


Hint Fast Full Scan
Se os campos da clusula SELECT e WHERE so combinados para formar um ndice, a
consulta ser executada mais rapidamente.
A Oracle no garante completamente a utilizao do ndice sob estas circunstncias. Por
causa disto vale a pena a utilizao do hint INDEX_FFS. Ele faz com que seja acessado
somente o ndice, e no a tabela.
SELECT /*+ INDEX_FFS(employees emp_idx1) */
ename
FROM employees
WHERE dept_no = 10

16. Casos Especiais (continuao)


Hint para Rapidez
Um hint no publicado, que foi citado em alguns fruns e salas de bate papo, dito como
um segredo escondido para melhoria de performance.
Parece que ele, de uma forma no documentada, percebe as melhores situaes para
resolver o plano de acesso de uma consulta. Difcil acreditar que algo assim exista.

SELECT /*+ richs_secret_hint */ emp_name, job


FROM employees
WHERE dept_no = 10 AND ename = ADAMS

16. Casos Especiais (continuao)


Cache de Tabela em Memria
Uma consuta sempre ser executa mais rapidamente pela segunda vez. Isto porque seus
blocos j estaro em memria. Baseado neste princpio surge a idia de manter fixado
dados na memria. No possvel fazer isto com todas as tabelas, mas podemos focar nas
que so menores e muito utilizadas.

ALTER TABLE customer CACHE;


SELECT cust_no, name
FROM customer
WHERE cust_no = 1

16. Casos Especiais (continuao)


Merge em ndices
Esta operao permite juntar (merge) dois ndices diferentes e usar o seu resultado, ao
invs de acessar os dados na tabela.
-- Tabela TEST com 1.000.000 de linhas e 210Mb de tamanho.
CREATE INDEX year_idx ON test (year);
CREATE INDEX state_idx ON test (state);

SELECT state, year


FROM test
WHERE year = 1972 AND state = MA
PLANO DE ACESSO
--------------SELECT STATEMENT Optimizer=HINT: RULE
TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
INDEX (RANGE SCAN) OF 'STATE_IDX' (NON-UNIQUE)

16. Casos Especiais (continuao)


Merge em ndices
SELECT /*+ index_join(test year_idx state_idx) */ state, year
FROM test
WHERE year = 1972 AND state = MA
PLANO DE ACESSO
--------------SELECT STATEMENT Optimizer=CHOOSE
VIEW OF 'index$_join$_001'
HASH JOIN
INDEX (RANGE SCAN) OF 'YEAR_IDX' (NON-UNIQUE)
INDEX (RANGE SCAN) OF 'STATE_IDX' (NON-UNIQUE)

Das könnte Ihnen auch gefallen