- Este tópico contém 13 respostas, 5 vozes e foi atualizado pela última vez 16 anos, 7 meses atrás por
vieri.
-
AutorPosts
-
16 de julho de 2009 às 8:56 pm #87954
apovoa
ParticipanteEstou com uma consulta entre duas tabelas e o comportamento
do plano de execução está um tanto quanto estranho, vejam só:
SELECT PE.SEQ_PESSOA
,PE.NOME_COMPLETO
,VI,CHAVE_ORIGEM
FROM PESSOA PE
,VINCULO VI
WHERE PE.SEQ_PESSOA = VI.SEQ_ENTIDADE_A
AND VI.FLAG_CARGA = 1;
O campo SEQ_PESSOA é a chave-primaria da tabela PESSOA, e
a tabela VINCULO tem um índice para o campo FLAG_CARGA.Pois bem, o oracle deveria usar estes índices, mas usa apenas o índice
da tabela VINCULO, e faz um FULLSCAN na tabela PESSOA, assim a consulta demora em torno de 10s.Se eu retirar do select o campo NOME_COMPLETO, o oracle passa a usar o índice da tabela PESSOA, e lógico, a consulta retorna intantâneamente.
Já executei o ANALYZE (DBMS_DDL.ANALYZE_OBJECT) para as referidas tabelas, e nada.
Alguém saberia me explicar o porquê disto, e como resolver (fora o uso de HINTS) ?
16 de julho de 2009 às 9:04 pm #87955vieri
ParticipanteSeq_entidade da tabela de vinculo
possui índice ?16 de julho de 2009 às 9:38 pm #87957Marcio68Almeida
ParticipanteBom…
Aqui nós temos um problema de conceito…
A consulta na tabela PESSOA é FULL pelo simples fato de você não estar restringindo um range de dados, a restrição existe na tabela VINCULO.
O fato de usar o índice caso você retire uma coluna do SELECT quer dizer que as colunas restantes pertencem a um índice e o Oracle vai fazer a busca mais “barata”, isto é, ao invés de consultar a tabela que tem várias colunas, consulta o índice que tem poucas.Se você colocar uma restrição na tabela PESSOA certamente o índice será usado.
16 de julho de 2009 às 9:47 pm #87959apovoa
Participante[quote=”vieri”:24rptaem]Seq_entidade da tabela de vinculo
possui índice ?[/quote]Não
abaixo os planos de execuçao
com o campo NOME_PESSOA
SELECT STATEMENT ALL_ROWSCost: 43,458 Bytes: 10.096.416 Cardinality: 229,464
5 HASH JOIN Cost: 43,458 Bytes: 10.096.416 Cardinality: 229,464
3 TABLE ACCESS BY INDEX ROWID TABLE SISPES.VINCULO Cost: 20,073 Bytes: 3.671.424 Cardinality: 229,464
2 BITMAP CONVERSION TO ROWIDS
1 BITMAP INDEX SINGLE VALUE INDEX (BITMAP) SISPES.VINCULO_I01
4 TABLE ACCESS FULL TABLE SISPES.PESSOA Cost: 18,216 Bytes: 70.614.096 Cardinality: 2.521.932
sem o campo NOM_PESSOA
SELECT STATEMENT ALL_ROWSCost: 23,628 Bytes: 4.818.744 Cardinality: 229,464
5 HASH JOIN Cost: 23,628 Bytes: 4.818.744 Cardinality: 229,464
3 TABLE ACCESS BY INDEX ROWID TABLE SISPES.VINCULO Cost: 20,073 Bytes: 3.671.424 Cardinality: 229,464
2 BITMAP CONVERSION TO ROWIDS
1 BITMAP INDEX SINGLE VALUE INDEX (BITMAP) SISPES.VINCULO_I01
4 INDEX FAST FULL SCAN INDEX (UNIQUE) SISPES.PESSOA_PK Cost: 1,133 Bytes: 12.609.660 Cardinality: 2.521.932
16 de julho de 2009 às 10:49 pm #87968lipcurl
ParticipanteAcho que o Márcio já deu a resposta.
Diga a finalidade da query.. Talvez possa incorporá-la em outra afim de que o acesso não seja full !
16 de julho de 2009 às 10:54 pm #87969David Siqueira
ParticipantePara efeito de teste de performance você pode tentar forçar o uso do indice da tabela pessoa, se nada mudar em termos de ganho , acredito que seja melhor analisar se esse indice é eficaz ou não, e seguir as recomendações do Márcio ajudaria em muito também.
Abraço.
16 de julho de 2009 às 11:00 pm #87972lipcurl
ParticipanteBem.. tente usar RULES.. Talvez melhore o desempenho ou vai piorar de vez.
17 de julho de 2009 às 6:14 pm #87982apovoa
ParticipanteA função da consulta é trazer alguns campos da tabela pessoa, que tenha vínculos que ainda não foram importados.
Ou seja, a restrição é na tabela vínculo, e da tabela pessoa a restrição é esta pessoa estar neste conjunto de registros selecionados da tabela vínculo.
Se eu forçar o uso do índice (PK) da tabela pessoa, a resposta é instantânea, porém eu gostaria de entender porquê o oracle não usa este índice por conta própria.
O uso de várias sub-consultas na query também faz usar o índice, mas não sei se isto é uma boa prática.
Não tenha acesso físico ao servidor, porém tenho privilégios de DBA, gostaria de aproveitar para saber como apagar e refazer as estatísticas usando DBMS_STATS, a versão é 10g.17 de julho de 2009 às 6:31 pm #87985Marcio68Almeida
ParticipanteBom…
Se você faz uma consulta na tabela PESSOA, o banco irá fazer um full table scan, não vai nem tentar usar um índice.
Se você colocar qualquer restrição, o banco irá verificar se há um índice que auxilie no processo.
Se você colocar um ORDER BY, é bem provável que ele use um índice.Não gosto de “forçar” o banco a utilizar um determinado índice através de hints, lá na frente (no futuro) não se saberá mais por que um ou outro recurso foi utilizado, isso acontece normalmente por falta de documentação.
Lembrando também que restrições com função do tipo TO_CHAR, TO_DATE, SUBSTR, etc., elimina a utilização do índice, a menos que o índice também possua tal função.
17 de julho de 2009 às 6:54 pm #87988vieri
ParticipanteConcordo comtudo que o Márcio falou…
mas faz um teste.
Cria um índice unico para cada coluna do join.
PE.SEQ_PESSOA = VI.SEQ_ENTIDADE_Arode a estatistica para as tabels e os índices
e ve o plano novamente.17 de julho de 2009 às 7:27 pm #87992Marcio68Almeida
ParticipanteOutra coisa…
O seu banco está por REGRA ou CUSTO ?
Às vezes, por mais estranho que possa parecer, se você remover as estatísticas o banco começa a usar o índice. Faça o teste.17 de julho de 2009 às 11:58 pm #87999apovoa
Participante[quote=”vieri”:2nk0r5pc]
Cria um índice unico para cada coluna do join.
PE.SEQ_PESSOA = VI.SEQ_ENTIDADE_A[/quote]Já existem
[quote=”Marcio68Almeida”:2nk0r5pc]Outra coisa…
O seu banco está por REGRA ou CUSTO ?
Às vezes, por mais estranho que possa parecer, se você remover as estatísticas o banco começa a usar o índice. Faça o teste.[/quote]Gostaria de saber como posso ver isto e como refazer as estatísticas usando DBMS_STATS.
18 de julho de 2009 às 12:11 am #88000David Siqueira
ParticipanteCara pra ver qual tipo de OPTIMIZER MODE seu banco usa basta vc se conectar no SQL e digitar :
show parameter opmizer_modevai aparecer qual você esta usando.
Quanto a DBMS_STATS vocÊ quer coletar de 1 unica tabela, de um schema inteiro, do banco todo, compute ou estimate?…tem todas essas questões a serem analisadas e que influenciaram demais no resultado final, que é a performance melhroada.
abraço.
20 de julho de 2009 às 7:19 pm #88017vieri
Participantealter session set optimizer_mode = rule;
alter session set optimizer_mode = choose;
alter session set optimizer_mode = all_rows;
alter session set optimizer_mode = first_rows;
tente com esses 4 alter sessions e ve se o plano muda…
-
AutorPosts
- Você deve fazer login para responder a este tópico.