Академический Документы
Профессиональный Документы
Культура Документы
(nr_nota_fiscal number
,Tipo_nota_fiscal number
,Data_nota_fiscal date
,Valor_nota_fiscal number);
DECLARE
V_MOD NUMBER;
BEGIN
if x = 1 then
v_mod := 5;
elsif x = 2 then
v_mod := 13;
elsif x = 3 then
v_mod := 19;
elsif x = 4 then
v_mod := 43;
else
v_mod := 198;
end if;
--> Insere a nota
(nr_nota_fiscal
,tipo_nota_fiscal
,data_nota_fiscal
,valor_nota_fiscal)
values
(y+v_mod
,x
,sysdate+y+x
,y+x);
END LOOP;
END LOOP;
commit;
END;
Agora, precisa identificar somente as últimas notas geradas para cada tipo específico de nota:
Select nr_nota_fiscal
from PLZ_NOTA_FISCAL
where tipo_nota_fiscal = 3
from PLZ_NOTA_FISCAL
where tipo_nota_fiscal = 3)
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
| 3 | SORT AGGREGATE | | 1 | 26 | | |
-------------------------------------------------------------------------------------------------
---------------------------------------------------
FROM "PLZ_NOTA_FISCAL"
WHERE "TIPO_NOTA_FISCAL"=3))
2 - access("TIPO_NOTA_FISCAL"=3)
5 - access("TIPO_NOTA_FISCAL"=3)
Agora vamos testar de outra maneira, só que desta vez usando as funções analíticas disponíveis no Oracle:
select tipo_nota_fiscal
, ultimo_numero
, tipo_nota_fiscal
, data_nota_fiscal
, valor_nota_fiscal
from PLZ_NOTA_FISCAL)
and tipo_nota_fiscal = 3
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter("NR_NOTA_FISCAL"="ULTIMO_NUMERO")
4 - access("TIPO_NOTA_FISCAL"=3)
Na busca usando subquery, ele gerou um custo maior e um plano de acesso onde acessou duas vezes a mesma
tabela e o mesmo índice.
Na busca usando funções analíticas, ele gerou um custo menor e um plano de acesso simplificado.
Agora, Vamos fazer o teste retornando o último número de notas fiscais para cada tipo existente:
Select nr_nota_fiscal
from PLZ_NOTA_FISCAL
, MAX(nr_nota_fiscal)
from PLZ_NOTA_FISCAL
group by tipo_nota_fiscal)
--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25000 | 1562K| 5 (40)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 3 | NESTED LOOPS | | | | | |
--------------------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter("NR_NOTA_FISCAL"=MAX("NR_NOTA_FISCAL"))
6 - access("TIPO_NOTA_FISCAL"="TIPO_NOTA_FISCAL")
select tipo_nota_fiscal
, ultimo_numero
, tipo_nota_fiscal
, data_nota_fiscal
, valor_nota_fiscal
from PLZ_NOTA_FISCAL)
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 500 | 19500 | 4 (25)| 00:00:01 |
---------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter("NR_NOTA_FISCAL"="ULTIMO_NUMERO")
Na busca pela subquery, ele retornou um número bem maior de linhas por causa da cardinalidade entre elas,
fazendo acesso full na tabela.
Na busca pela função analítica, ele retornou o número exato de bytes existentes na tabela por não gerar
cardinalidade, o que resulta num custo menor, apesar do acesso full.
Apesar da pouca diferença do custo, a diferença no consumo de CPU bem como no número de linhas e bytes
processados foi significativo.
Conclusão
Substituir a subquery por uma função analítica nestes casos pode gerar um ganho significativo de desempenho,
especialmente se esse comando é executando dentro de um loop.