- Este tópico contém 9 respostas, 4 vozes e foi atualizado pela última vez 14 anos, 5 meses atrás por
fsitja.
-
AutorPosts
-
29 de março de 2010 às 6:30 pm #93385
ramasine
ParticipanteSrs,
Base de dados 11.2 (OLTP) em aix 6.1
Tenho uma consulta que necessita juntar duas tabelas de log: a A007 (anomalias) e a ATM_LOG (transacções de ATM, incluindo anomalias).
A A007 funciona como tabela de extensão guardando apenas os dados a ela exclusivos. A ATM_LOG guarda os dados gerais (incluindo o ATM_CODE, algo essencial para a pesquisa e motivo pelo qual o join lá se encontra)!
O select é o seguinte:
SELECT
T1.CLEARING_PERIOD,
T1.TRANSACTION_ID,
T2.BANK_CARD_BANK_CODE,
T2.BANK_CARD_NUMBER,
T2.ATM_CARD_CAPTURE_REASON,
T2.ATM_PERIOD_NUMBER_ROUND,
T2.DID_CANCEL_LAST_TRANSACTION,
T2.CLEARING_PERIOD_FOR_CANCEL,
T2.TRANSACTION_ID_FOR_CANCEL,
T2.ATM_PERIOD_NUMBER_REC,
T2.ATM_CODE,
T2.ATM_TRANSACTION_CODE,
T2.TRANSACTION_TIMESTAMP,
T2.TRANSACTION_STATUS,
T2.APPLICATION_CODE_ERROR,
T1.ANOMALY_TYPE,
T1.ATM_ANOMALY_CODE,
T1.OPERATION_MOMENT,
T1.ATM_HARDWARE_ANOMALY,
T1.ATM_ERROR_TEXT,
T1.BANK_CARD_TRACK2_TLV,
T1.BANK_CARD_TRACK3_TLV,
T1.PRIM_ACC_NBR_PAN_TLV,
T1.APP_EXPIRATION_DATE_TLV,
T1.CHIP_PROC_RESULT_TLV,
T1.CLEARING_FLAG,
T1.CAPTURE_CARD_INDICATOR,
T1.CAPTURE_CARD_ID
From A007_T T1 LEFT OUTER JOIN ATM_LOG T2 ON T1.CLEARING_PERIOD = T2.CLEARING_PERIOD And T1.TRANSACTION_ID = T2.TRANSACTION_ID
Where T1.CLEARING_PERIOD >= 529 And T1.CLEARING_PERIOD <= 529 Order by CLEARING_PERIOD desc, TRANSACTION_ID desc O explain plan mostra o porquê da demora: aparentemente é feito um full table scan à tabela A007 (quando se restringe a um período com muitas anomalias) e o join com a ATM_LOG é pelas chaves primárias e por aqui talvez não haja problema: Plan SELECT STATEMENT ALL_ROWS Cost: 2,742 Bytes: 231,192 Cardinality: 1,352 Partition #: 0 5 SORT ORDER BY Cost: 2,742 Bytes: 231,192 Cardinality: 1,352 Partition #: 0 4 NESTED LOOPS OUTER Cost: 2,741 Bytes: 231,192 Cardinality: 1,352 Partition #: 0 1 TABLE ACCESS FULL EPMS_CC.A007_T Cost: 34 Bytes: 158,184 Cardinality: 1,352 Partition #: 0 3 TABLE ACCESS BY INDEX ROWID EPMS_CC.ATM_LOG Cost: 2 Bytes: 54 Cardinality: 1 Partition #: 0 2 INDEX UNIQUE SCAN EPMS_CC.ATM_LOG_PK Cost: 1 Bytes: 0 Cardinality: 1 Partition #: 0 Pergunta: Existe alguma forma simples de melhorar esta pesquisa? Agradeço qq dica ou ajuda!30 de março de 2010 às 12:44 am #93419Leonardo Litz
ParticipanteOlá ramasine já tentou utilizar a Hint de Index? Tente forçar a utilização do indice da tabela A007_T
Vlw Leonardo Litz
30 de março de 2010 às 2:20 pm #93422ramasine
ParticipanteValeu Léo!
Já sugeri isso a galera de DEV, estou aguardando feedback!Queria substituir a notação LEFT OUTER JOIN pelo (+), sabe dizer como ficaria nessa query?
ABs
30 de março de 2010 às 3:33 pm #93424Leonardo Litz
ParticipanteSegue:
SELECT T1.CLEARING_PERIOD,
T1.TRANSACTION_ID,
T2.BANK_CARD_BANK_CODE,
T2.BANK_CARD_NUMBER,
T2.ATM_CARD_CAPTURE_REASON,
T2.ATM_PERIOD_NUMBER_ROUND,
T2.DID_CANCEL_LAST_TRANSACTION,
T2.CLEARING_PERIOD_FOR_CANCEL,
T2.TRANSACTION_ID_FOR_CANCEL,
T2.ATM_PERIOD_NUMBER_REC,
T2.ATM_CODE,
T2.ATM_TRANSACTION_CODE,
T2.TRANSACTION_TIMESTAMP,
T2.TRANSACTION_STATUS,
T2.APPLICATION_CODE_ERROR,
T1.ANOMALY_TYPE,
T1.ATM_ANOMALY_CODE,
T1.OPERATION_MOMENT,
T1.ATM_HARDWARE_ANOMALY,
T1.ATM_ERROR_TEXT,
T1.BANK_CARD_TRACK2_TLV,
T1.BANK_CARD_TRACK3_TLV,
T1.PRIM_ACC_NBR_PAN_TLV,
T1.APP_EXPIRATION_DATE_TLV,
T1.CHIP_PROC_RESULT_TLV,
T1.CLEARING_FLAG,
T1.CAPTURE_CARD_INDICATOR,
T1.CAPTURE_CARD_ID
From A007_T T1,
ATM_LOG T2
where T1.CLEARING_PERIOD = T2.CLEARING_PERIOD(+)
and T1.TRANSACTION_ID = T2.TRANSACTION_ID(+)
and T1.CLEARING_PERIOD >= 529
And T1.CLEARING_PERIOD <= 529
Order by CLEARING_PERIOD desc, TRANSACTION_ID desc
30 de março de 2010 às 6:12 pm #93435ramasine
ParticipanteObrigado Léo!
Mais uma dúvida, abusando..rss
To tentando entender porque é que, para o Oracle, é mais fácil realizar um full table scan na A007 do que utilizar o seu índice de chave primária, que é composto pelo período e pelo nº de transacção, para utilizar um subconjunto menor de dados. Não sei como é que internamente os dados são obtidos.
Abs
30 de março de 2010 às 6:39 pm #93441burga
ParticipanteBasicamente é porque utilizando o indice, o Oracle vai fazer a leitura de um bloco de cada vez, e no full table ele lê vários blocos sequenciados de uma só vez.
Ou seja, se você for ler uma porcentagem alta de registros da tabela, normalmente fica menos custoso fazer um full table do que ler bloco a bloco.
Aqui tem um link que o Tom explica de uma forma fácil de entender o que ocorre no full tabe x indices:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4433887271030
30 de março de 2010 às 7:28 pm #93443ramasine
ParticipanteValeu Tajiri….muito obrigado!!
30 de março de 2010 às 8:21 pm #93444Leonardo Litz
ParticipanteE completando…
Quando é executado um other join, o Oracle lista todas os registros antes de posteriormente tenta o relacionamento. Ao listar todos os registro utiliza o full table scan.
Vlw Leonardo Litz
31 de março de 2010 às 1:04 am #93453fsitja
ParticipanteO negócio é imaginar que, se você vai ler um livro, se você quer ler ele inteiro (ou a maior parte dele), você não procura no índice antes de virar cada página. Você simplesmente vira todas as páginas na sequência, pulando aquelas que eventualmente não interessam.
No Oracle é a mesma coisa, como seu select pede por várias colunas que não estão no índice, o banco de dados precisa:
1 – ler no índice (IO = custa caro)
2 – Descobrir se vai querer usar aquela linha (avaliar predicado where)
3 – Acessar o bloco da tabela em si, pois o select pediu colunas que não estão no índice ( = mais IO, caro em dobro, pois lê duas vezes a mesma coisa, uma vez no índice para filtrar e outra na tabela para exibir).Logo, se o CBO estima que seu WHERE vai acabar por querer um percentual relativamente alto das linhas da tabela (> 10-15% já é alto) ele vai direto na tabela pois ler índice só é vantagem se for buscar a agulha escondida no palheiro.
31 de março de 2010 às 1:12 am #93455fsitja
Participante[quote=”Litz”:wwr520ye]E completando…
Quando é executado um other join, o Oracle lista todas os registros antes de posteriormente tenta o relacionamento. Ao listar todos os registro utiliza o full table scan.
Vlw Leonardo Litz[/quote]
O Where é avaliado antes de decidir por full table scan ou não, mas de fato o left outer join, ou o (+) que é a mesma coisa, torna o plano de execução mais “pessismista” do que para um inner join pois é preciso retornar todas linhas da tabela à esquerda independente da condição de join ser satisfeita ou não.
Para a avaliação do where ser precisa o ideal seria existir um índice em T1.CLEARING_PERIOD com estatísticas e histogramas atualizados.
-
AutorPosts
- Você deve fazer login para responder a este tópico.