- Este tópico contém 14 respostas, 5 vozes e foi atualizado pela última vez 16 anos, 7 meses atrás por
CleitonHanzen.
-
AutorPosts
-
27 de julho de 2009 às 7:34 pm #88219
ramasine
ParticipanteCaros colegas!
Tenho a seguinte query, que está lenta! (Oracle 9.2.0. 8)
SELECT terper.out_num_ter, ter.out_nome, terper.per_codigo, per_descricao
FROM fin_perfil per, fin_out_ter ter, fin_out_ter_per terper
WHERE terper.out_num_ter = ter.out_num_ter
AND terper.per_codigo = per.per_codigo
ORDER BY 1, 3Plano
Plan
SELECT STATEMENT CHOOSECost: 410 Bytes: 1 576 500 Cardinality: 15 765
6 SORT ORDER BY Cost: 410 Bytes: 1 576 500 Cardinality: 15 765
5 HASH JOIN Cost: 57 Bytes: 1 576 500 Cardinality: 15 765
3 HASH JOIN Cost: 14 Bytes: 292 187 Cardinality: 5 963
1 TABLE ACCESS FULL FIN.FIN_PERFIL Cost: 3 Bytes: 2 706 Cardinality: 82
2 INDEX FULL SCAN UNIQUE FIN.OTP_PK Cost: 48 Bytes: 95 408 Cardinality: 5 963
4 TABLE ACCESS FULL FIN.FIN_OUT_TER Cost: 40 Bytes: 804 015 Cardinality: 15 765Alterei para:
SELECT terper.out_num_ter,
(SELECT out_nome
FROM fin_out_ter ter
WHERE terper.out_num_ter = ter.out_num_ter) out_nome,
terper.per_codigo,
(SELECT per_descricao
FROM fin_perfil per
WHERE terper.per_codigo = per.per_codigo) per_descricao
FROM fin_out_ter_per terper
WHERE 1 = 1
ORDER BY 1, 3e o plano gerado foi este!
Plan
SELECT STATEMENT CHOOSECost: 14 Bytes: 95 408 Cardinality: 5 963
2 TABLE ACCESS BY INDEX ROWID FIN.FIN_OUT_TER Cost: 2 Bytes: 51 Cardinality: 1
1 INDEX UNIQUE SCAN UNIQUE FIN.OUT_PK Cost: 2 Cardinality: 1
4 TABLE ACCESS BY INDEX ROWID FIN.FIN_PERFIL Cost: 2 Bytes: 33 Cardinality: 1
3 INDEX UNIQUE SCAN UNIQUE FIN.PER_PK Cost: 1 Cardinality: 1
6 SORT ORDER BY Cost: 14 Bytes: 95 408 Cardinality: 5 963
5 INDEX FULL SCAN UNIQUE FIN.OTP_PK Cost: 48 Bytes: 95 408 Cardinality: 5 963Pq é que nesse segundo caso a query ficou bem mais rápida, e sem os full table scans?
Obrigado!!
Marcelo
27 de julho de 2009 às 8:25 pm #88222Ishii
ParticipanteOlá,
Aparentemente na primeira query a tabela fin_perfil não tem relacionamento com a fin_out_ter e isso não irá satisfazer a condição de relacionamento entre a fin_out_ter e fin_out_ter_per, por isso a query sempre irá fazer um full scan nessas tabelas.
Já na segunda query, o relacionamento da fin_out_ter_per diretamente com a fin_perfil sem a outra tabela fin_out_ter evitou o full scan. Não sei a sua MER mas a tabela fin_out_ter_per deve ser n para n com fin_perfil por causa da tabela fin_out_ter… Se todas as três tabelas tem relacionamento entre si (com todas as três) faltou alguma condição na primeira query.
[]s Ishii
27 de julho de 2009 às 8:37 pm #88224ramasine
ParticipanteObrigado ISHII!
O que me parece tb é na segunda query os ROWID estão sendo utilizados na busca pelos registros!!
28 de julho de 2009 às 12:12 am #88243mpvargas
ParticipanteCompanheiros,
Aproveitando o assunto…
Como deve fazer para gerar os planos de acesso e calcular esses valores de acessos as queries?
Tem alguma ferramenta que vocês recomendam?
Obrigado.28 de julho de 2009 às 2:55 am #88249Ishii
ParticipanteOlá,
Eu uso o tkprof mesmo. Como já disse nosso amigo Portilho “This is Esparta”
[]s Ishii
28 de julho de 2009 às 12:31 pm #88252ramasine
ParticipanteSim TKPROF, e o ORADEBUG..são invariavelmente infalíveis!!
Esse link dá uma ilustrada!
http://www.oracleutilities.com/SQLPLus/oradebug.html
Abs
Marcelo Ramasine28 de julho de 2009 às 2:43 pm #88253ramasine
ParticipanteTenho essa query!
SELECT terper.out_num_ter, ter.out_nome, terper.per_codigo, per_descricao
FROM fin_perfil per, fin_out_ter ter, fin_out_ter_per terper
WHERE terper.out_num_ter = ter.out_num_ter
AND terper.per_codigo = per.per_codigo
ORDER BY 1, 3Plano
Plan
SELECT STATEMENT CHOOSECost: 646 Bytes: 2 575 172 Cardinality: 27 991
6 SORT ORDER BY Cost: 646 Bytes: 2 575 172 Cardinality: 27 991
5 HASH JOIN Cost: 60 Bytes: 2 575 172 Cardinality: 27 991
3 HASH JOIN Cost: 15 Bytes: 711 227 Cardinality: 17 347
1 TABLE ACCESS FULL FIN.FIN_PERFIL Cost: 3 Bytes: 2 706 Cardinality: 82
2 INDEX FULL SCAN UNIQUE FIN.OTP_PK Cost: 48 Bytes: 138 776 Cardinality: 17 347
4 TABLE ACCESS FULL FIN.FIN_OUT_TER Cost: 40 Bytes: 804 015 Cardinality: 15 765Se eu utilizar o select para obter os dados, em vez de ter o inner join às tabelas que contem os dados, o custo do otimizador é muito superior! Existem índices que ligam estas tabelas, porque que mesmo assim está sendo feito um full table scan em ambas as tabelas?
28 de julho de 2009 às 3:11 pm #88254Ishii
ParticipanteOlá,
Isso pode estar acontecendo pelo fato das estatísticas estarem desatualizadas. Atualize as estatísticas (acho que uns 20% já está suficiente) e refaça a query, pode ser que o Oracle passe a usar o índice.
[]s Ishii
28 de julho de 2009 às 3:30 pm #88256ramasine
ParticipanteAtualizei para 20% com o DBMS_STATS, e nada, continua na mesma!
Lógico que com o CASCADE=TRUE28 de julho de 2009 às 3:53 pm #88257Ishii
ParticipanteOlá,
Bom, essa é uma das razões que eu, particularmente, prefiro o RULE em vez de CHOOSE… algumas vezes as escolhas do Otimizador são meio estranhas e nem sempre tem uma explicação…
Faça a query com um hint e verifique a performance:
SELECT /*+ rule */ terper.out_num_ter, ter.out_nome, terper.per_codigo, per_descricao
FROM fin_perfil per, fin_out_ter ter, fin_out_ter_per terper
WHERE terper.out_num_ter = ter.out_num_ter
AND terper.per_codigo = per.per_codigo
ORDER BY 1, 3
Outro teste mais xiita seria atualizar a estatística para 100% e tentar sem o hint…
[]s Ishii
28 de julho de 2009 às 4:45 pm #88259David Siqueira
ParticipanteRamasine, desculpe a intromissão, mas você pode utilizar também o Automatic Tunning se sua base for 10g :
http://www.oracle-base.com/articles/10g/AutomaticSQLTuning10g.php
Abração
28 de julho de 2009 às 5:07 pm #88263ramasine
ParticipanteDavid, é 9.2.0.8 !
28 de julho de 2009 às 5:21 pm #88265CleitonHanzen
Participante[quote=”ramasine”:3ov3ew5a]Tenho essa query!
SELECT terper.out_num_ter, ter.out_nome, terper.per_codigo, per_descricao
FROM fin_perfil per, fin_out_ter ter, fin_out_ter_per terper
WHERE terper.out_num_ter = ter.out_num_ter
AND terper.per_codigo = per.per_codigo
ORDER BY 1, 3Plano
Plan
SELECT STATEMENT CHOOSECost: 646 Bytes: 2 575 172 Cardinality: 27 991
6 SORT ORDER BY Cost: 646 Bytes: 2 575 172 Cardinality: 27 991
5 HASH JOIN Cost: 60 Bytes: 2 575 172 Cardinality: 27 991
3 HASH JOIN Cost: 15 Bytes: 711 227 Cardinality: 17 347
1 TABLE ACCESS FULL FIN.FIN_PERFIL Cost: 3 Bytes: 2 706 Cardinality: 82
2 INDEX FULL SCAN UNIQUE FIN.OTP_PK Cost: 48 Bytes: 138 776 Cardinality: 17 347
4 TABLE ACCESS FULL FIN.FIN_OUT_TER Cost: 40 Bytes: 804 015 Cardinality: 15 765Se eu utilizar o select para obter os dados, em vez de ter o inner join às tabelas que contem os dados, o custo do otimizador é muito superior! Existem índices que ligam estas tabelas, porque que mesmo assim está sendo feito um full table scan em ambas as tabelas?[/quote]
Opá…
Desculpe a intromissão, mas com optimizer=choose, all_rows ou first_rows (baseado em custos/estatísticas), nem sempre a existência de índice fará o otimizador utilizar este índice e isso pode ocorrer por vários motivos q vão desde a distribuição das chaves (cardinalidade muito elevada, e o otimizador considera menos “custo” fazer Full table scan) até índices fragmentados…
Mas outro detalhe que observei na tua query, é que todos os registros das tabelas envolvidas vão ter que ser lidos, pois não está sendo passada restrição nenhuma (somente está sendo feita a comparação entre as tabelas, mas não existe uma cláusula restritiva “where campo=100” por exemplo)….
Indepente do custo que a query está gerando, iria fazer um teste de deixá-las rodando e iria cronometrar o tempo, às vezes o Full table scan pode ser mais custoso mas retorna mais rápido os registros…. 😉
28 de julho de 2009 às 6:35 pm #88271ramasine
ParticipanteOpa!!
Sim, estou vendo essa parte tb, não há restrição na primeira query!Agora, vcs podem parar de ficar pedindo desculpa pela intromissão?? rss
Não há pq!!Valeu!!
Marcelo
28 de julho de 2009 às 6:52 pm #88273CleitonHanzen
Participantersrsrsrs..
É que o ishi tava de “teu fiel ajudante”…..
flws…
-
AutorPosts
- Você deve fazer login para responder a este tópico.