Pular para o conteúdo
  • Este tópico contém 14 respostas, 5 vozes e foi atualizado pela última vez 16 anos, 7 meses atrás por CleitonHanzen.
Visualizando 15 posts - 1 até 15 (de 15 do total)
  • Autor
    Posts
  • #88219
    ramasine
    Participante

      Caros 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, 3

      Plano

      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 765

      Alterei 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, 3

      e 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 963

      Pq é que nesse segundo caso a query ficou bem mais rápida, e sem os full table scans?

      Obrigado!!

      Marcelo

      #88222
      Ishii
      Participante

        Olá,

        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

        #88224
        ramasine
        Participante

          Obrigado ISHII!

          O que me parece tb é na segunda query os ROWID estão sendo utilizados na busca pelos registros!!

          #88243
          mpvargas
          Participante

            Companheiros,
            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.

            #88249
            Ishii
            Participante

              Olá,

              Eu uso o tkprof mesmo. Como já disse nosso amigo Portilho “This is Esparta”

              []s Ishii

              #88252
              ramasine
              Participante

                Sim TKPROF, e o ORADEBUG..são invariavelmente infalíveis!!

                Esse link dá uma ilustrada!

                http://www.oracleutilities.com/SQLPLus/oradebug.html

                Abs
                Marcelo Ramasine

                #88253
                ramasine
                Participante

                  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, 3

                  Plano

                  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 765

                  Se 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?

                  #88254
                  Ishii
                  Participante

                    Olá,

                    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

                    #88256
                    ramasine
                    Participante

                      Atualizei para 20% com o DBMS_STATS, e nada, continua na mesma!
                      Lógico que com o CASCADE=TRUE

                      #88257
                      Ishii
                      Participante

                        Olá,

                        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

                        #88259
                        David Siqueira
                        Participante

                          Ramasine, 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

                          #88263
                          ramasine
                          Participante

                            David, é 9.2.0.8 !

                            #88265
                            CleitonHanzen
                            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, 3

                              Plano

                              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 765

                              Se 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…. 😉

                              #88271
                              ramasine
                              Participante

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

                                #88273
                                CleitonHanzen
                                Participante

                                  rsrsrsrs..

                                  É que o ishi tava de “teu fiel ajudante”…..

                                  flws…

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