Pular para o conteúdo
Visualizando 14 posts - 1 até 14 (de 14 do total)
  • Autor
    Posts
  • #87954
    apovoa
    Participante

      Estou 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) ?

      #87955
      vieri
      Participante

        Seq_entidade da tabela de vinculo
        possui índice ?

        #87957
        Marcio68Almeida
        Participante

          Bom…
          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.

          #87959
          apovoa
          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

            #87968
            lipcurl
            Participante

              Acho 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 !

              #87969
              David Siqueira
              Participante

                Para 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.

                #87972
                lipcurl
                Participante

                  Bem.. tente usar RULES.. Talvez melhore o desempenho ou vai piorar de vez.

                  #87982
                  apovoa
                  Participante

                    A 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.

                    #87985
                    Marcio68Almeida
                    Participante

                      Bom…
                      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.

                      #87988
                      vieri
                      Participante

                        Concordo 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_A

                        rode a estatistica para as tabels e os índices
                        e ve o plano novamente.

                        #87992
                        Marcio68Almeida
                        Participante

                          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.

                          #87999
                          apovoa
                          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.

                            #88000
                            David Siqueira
                            Participante

                              Cara pra ver qual tipo de OPTIMIZER MODE seu banco usa basta vc se conectar no SQL e digitar :

                              show parameter opmizer_mode

                              vai 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.

                              #88017
                              vieri
                              Participante

                                alter 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…

                              Visualizando 14 posts - 1 até 14 (de 14 do total)
                              • Você deve fazer login para responder a este tópico.