Pular para o conteúdo
Visualizando 8 posts - 1 até 8 (de 8 do total)
  • Autor
    Posts
  • #89503
    ramasine
    Participante

      Caros,

      Tenho o select abaixo, como parte de uma procedure que está com a performance muito lenta!!!!!

      Existe, a nível de ORACLE, diferença de performance para que o select count(1) seja bem mais rápido do que o select “normal” na tabela?

      17:45:49 sql’@’sigt > SELECT DISTINCT par.sdo_gid, par.geocodigo
      17:46:36 2 FROM sivvapp.dados dad, sivv_sp.parcela par
      17:46:36 3 WHERE dad.parcela_tipo_cultura != 16
      17:46:36 4 AND dad.parcela_id = par.attr_id
      17:46:36 5 AND par.delete_date IS NULL;

      772628 rows selected.

      Execution Plan
      ———————————————————-
      0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=42541 Card=950369 Bytes=31362177)
      1 0 SORT (UNIQUE) (Cost=42541 Card=950369 Bytes=31362177)
      2 1 HASH JOIN (Cost=33851 Card=950369 Bytes=31362177)
      3 2 TABLE ACCESS (FULL) OF ‘DADOS’ (TABLE) (Cost=16853 Card=950369 Bytes=8553321)
      4 2 TABLE ACCESS (FULL) OF ‘PARCELA’ (TABLE) (Cost=14139 Card=1065910 Bytes=25581840)

      Esse select demora muito..

      E o count dele, apenas 12 segundos!

      TO_CHAR(
      ——–
      10:19:02

      COUNT(1)–DISTINCTPAR.SDO_GID,PAR.GEOCODIGO
      ——————————————-
      780053

      TO_CHAR(
      ——–
      10:19:15

      A base de dados é 10.1.0.5..

      As tabelas DADOS E PARCELAS tem 1.000.000 linhas cada…
      Sendo que a DADOS não tinha nenhum índice, nem sequem UNIQUE ou PK…o select acima ta varrendo 1 milhão de linhas obrigatoriamente!!

      Sugeri a mudança no SQL, que ficou assim:
      O pessoal de DEV ainda esqueceu de colocar o sinal de + no hint de APPEND..

      SELECT /*+ PARALLEL(sivv_sp.parcela,4) */ par.sdo_gid, par.geocodigo
      from sivv_sp.parcela par
      where exists (
      select /*+ PARALLEL(sivvapp.dados,4) */ 1 from sivvapp.dados dad
      where dad.parcela_tipo_cultura <>’16’
      and dad.parcela_id = par.attr_id)
      AND nvl(to_char(par.delete_date, ‘YYYYMMDD’),’null’) = ‘null’

      Mais que ainda demora muito!!

      O código da PROCEDURE, segue abaixo, TB sugeri o INSERT APPEND, pq a tabela a receber as linhas esta em NOLOGGING…apesar de saber que a eficiencia do append é comprovada em inserts diretos, sem que estes estejam dentro de cursores e procedures…, é isso mesmo?

      CREATE OR REPLACE PROCEDURE SIG.ivv_load IS
      CURSOR c_id IS
      SELECT /*+ PARALLEL(sivv_sp.parcela,4) */ DISTINCT par.sdo_gid, par.geocodigo
      FROM sivv_sp.parcela par
      WHERE EXISTS (SELECT /*+ PARALLEL(sivvapp.dados,4) */ 1 FROM sivvapp.dados dad
      WHERE dad.parcela_tipo_cultura <>’16’
      AND dad.parcela_id = par.attr_id)
      AND nvl(to_char(par.delete_date, ‘YYYYMMDD’),’null’) = ‘null’;

      CURSOR c_geo (p_sdo_gid NUMBER)
      IS
      SELECT tp_a.area
      FROM sivv_sp_topo.tp$_topo_c tp_c,
      sivv_sp_topo.tp$_topo_ca tp_ca,
      sivv_sp_topo.tp$_topo_a tp_a
      WHERE tp_c.geom_id = p_sdo_gid
      AND tp_c.delete_date IS NULL
      AND tp_c.centroid_id = tp_ca.centroid_id
      AND tp_ca.delete_date IS NULL
      AND tp_ca.area_id = tp_a.area_id
      AND tp_a.delete_date IS NULL;

      m_sdo_gid sivv_sp.parcela.sdo_gid%TYPE;
      m_geocodigo sivv_sp.parcela.geocodigo%TYPE;
      m_geo sivv_sp_topo.tp$_topo_a.area%TYPE;
      m_geo_wkb BLOB;
      m_pla_id sig.sig_psa_layer.pla_id%TYPE;
      m_int_val INTEGER;
      m_mip_id sig.sig_mig_itm_pol.mip_id%TYPE;
      m_mdi_id sig.sig_mig_det_itm.mdi_id%TYPE;
      c_sdo_srid CONSTANT NUMBER (6) := 262152;

      num_linhas PLS_INTEGER := 0;
      BEGIN
      — NOVO LAYER
      m_pla_id :=
      sig.psa_layer.put (2565,
      ‘Vinha do SIVV’,
      ‘pt.inga.layers.server.QueryLayer’,
      1,
      1,
      0
      );
      — NOVA MIGRAÇÃO
      m_int_val :=
      sig.migracao.put (m_pla_id,
      2,
      ‘Migração de Vinha do SIVV’,
      NULL,
      0,
      3071,
      0
      );
      — CAMPOS DA MIGRAÇÃO
      m_int_val := sig.mig_cam.put (NULL, m_pla_id, ‘IDIVV’);
      m_int_val := sig.mig_cam.put (NULL, m_pla_id, ‘GEOCODIGO’);

      — VINHA
      FOR r_id IN c_id
      LOOP
      — GEOMETRIA
      OPEN c_geo (r_id.sdo_gid);

      FETCH c_geo
      INTO m_geo;

      IF c_geo%FOUND
      THEN
      — UPDATE COORDINATE SYSTEM
      m_geo.sdo_srid := 262152;
      — SIMPLIFY GEOMETRY
      m_geo :=
      sdo_util.simplify (m_geo,
      misc.get_tol_inf_esp_cruzamentos,
      misc.get_tol_inf_esp_cruzamentos
      );

      SELECT sig_mig_itm_pol_seq.NEXTVAL
      INTO m_mip_id
      FROM DUAL;

      INSERT /* APPEND */ INTO sig_mig_itm_pol
      (mip_id, pla_id, mip_poligono, mip_poligono_wkb,
      mip_inf_int, mip_obs, est_vdo_id)
      VALUES
      (m_mip_id, m_pla_id, m_geo, sdotowkb (m_geo),
      NULL, NULL, 3063);

      — DETALHES
      m_mdi_id :=
      sig.mig_det_itm.put (NULL,
      m_mip_id,
      NULL,
      1,
      1,
      ‘IDIVV’,
      r_id.sdo_gid,
      NULL,
      ‘System.Int32,mscorlib’
      );
      m_mdi_id :=
      sig.mig_det_itm.put (NULL,
      m_mip_id,
      NULL,
      1,
      1,
      ‘GEOCODIGO’,
      r_id.geocodigo,
      NULL,
      ‘System.String,mscorlib’
      );
      num_linhas := num_linhas + 1;
      IF mod(num_linhas, 1000) = 0 THEN
      COMMIT;
      END IF;
      END IF;

      CLOSE c_geo;
      END LOOP;

      CLOSE c_id;
      END ivv_load;
      /

      Qq ajuda é bem-vinda!!

      Muito Obrigado!!

      #89504
      Avatar photoLeonardo Litz
      Participante

        Seguinte ramasine.

        Uma coisa que da para mudar:

        1 – Veja que existem dois loops encadeados, um o for no cursor c_id e dentro dele o fetch no cursor c_geo. Tente juntar os dois cursores em um so, se houver relacao entre a query do cursor c_id com c_geo voce efetua o insert. Isso fara com que vc faca um execute a cada passada do cursor c_id no cursor c_geo.
        2 – Tire o select do nextval do dual, coloque o direto no insert sig_mig_itm_pol_seq.NEXTVAL.
        3 – Depois de junto os cursores, utilize bulk collect neles, veja em:

        [url]http://imasters.uol.com.br/artigo/12960/oracle/utilizando_cursores_no_oracle/
        [/url]

        Espero que ajude.

        Vlw Leonardo Litz

        #89506
        ramasine
        Participante

          Valeu Léo!!!

          Vi que na tabela referida no INSERT, há constraints e uma trigger que atualiza uma tabela de histórico, é bem provável que se eu desabilitar essas constraints e essa trigger, a velocidade do insert aumente…!

          O que acham?

          #89507
          Avatar photoLeonardo Litz
          Participante

            Provavelmente.

            O seu insert sera mais rapido. O problema e a integridade dos dados neh.
            Voce pode colocar em keep pool essa tabela tb, isso tornara mais rapido o acesso tb.

            Vlw Leonardo Litz

            #89511
            ramasine
            Participante

              Galera,

              Fiz um trace no processo e pude verificar que a parte que esta mais lenta é o insert mesmo, pois esta a usar uma função BLOB e com isso o Oracle usa um componente chamado dbms_lob.createTemporary e é nesse momento que o processo fica mais lento.

              O tal do componente é iniciado por que no insert faz uso de uma função chamada “sdotowkb”.

              Acho que é nesse momento que temos uma lentidão no processo.

              INSERT /* APPEND */ INTO sig_mig_itm_pol
              (mip_id, pla_id, mip_poligono, mip_poligono_wkb,
              mip_inf_int, mip_obs, est_vdo_id) VALUES
              (m_mip_id, m_pla_id, m_geo, sdotowkb (m_geo),NULL, NULL, 3063);

              Trace:

              begin dbms_lob.createTemporary (:1,TRUE, :2); end;

              call count cpu elapsed disk query current rows

              ——- —— ——– ———- ———- ———- ———- ———-

              Parse 2219 0.15 0.16 0 0 0 0

              Execute 2219 1337.09 1849.30 0 0 0 2219

              Fetch 0 0.00 0.00 0 0 0 0

              ——- —— ——– ———- ———- ———- ———- ———-

              total 4438 1337.24 1849.47 0 0 0 2219

              Misses in library cache during parse: 0
              Optimizer mode: ALL_ROWS
              Parsing user id: 55 (recursive depth: 2)

              Alguem sabe se esse componente geralmente pode mesmo causar essa lentidão?

              dbms_lob.createTemporary

              Obrigado!!

              #89552
              vieri
              Participante

                Verifique se os LOB’s estão em uma tablespace dedicada
                somente a ele.

                Acho que vc não tem muito oque mecher nesses insert’s,
                ele já está com /APPEND/ que é mais rápido,
                pq grava no fim do datafile, não procura espaço em branco.

                Insert com lob’s são pesados por natureza…

                essa base está em storage ou disco local ?

                #89553
                vieri
                Participante

                  verifique qual wait event a sessão está recebendo…
                  pode está com problema de latch ou algo do genêro…

                  #89554
                  fsitja
                  Participante

                    Só um lembrete, na sua query modificada a última linha do exists tem

                    AND nvl(to_char(par.delete_date, 'YYYYMMDD'),'null')

                    como você colocou funções de nvl e to_char sobre a coluna “delete” e fez uma comparação no where, se há algum índice ali ele não será usado.

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