- Este tópico contém 7 respostas, 4 vozes e foi atualizado pela última vez 16 anos, 6 meses atrás por
fsitja.
-
AutorPosts
-
5 de setembro de 2009 às 10:50 pm #89503
ramasine
ParticipanteCaros,
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:02COUNT(1)–DISTINCTPAR.SDO_GID,PAR.GEOCODIGO
——————————————-
780053TO_CHAR(
——–
10:19:15A 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!!
6 de setembro de 2009 às 2:40 am #89504Leonardo Litz
ParticipanteSeguinte 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
7 de setembro de 2009 às 3:07 am #89506ramasine
ParticipanteValeu 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?
7 de setembro de 2009 às 9:56 am #89507Leonardo Litz
ParticipanteProvavelmente.
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
7 de setembro de 2009 às 11:04 pm #89511ramasine
ParticipanteGalera,
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!!
9 de setembro de 2009 às 11:12 pm #89552vieri
ParticipanteVerifique 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 ?
9 de setembro de 2009 às 11:13 pm #89553vieri
Participanteverifique qual wait event a sessão está recebendo…
pode está com problema de latch ou algo do genêro…10 de setembro de 2009 às 12:13 am #89554fsitja
ParticipanteSó 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. -
AutorPosts
- Você deve fazer login para responder a este tópico.