Pergunta

De repente (mas infelizmente não sei quando "de repente" foi; eu sei que funcionava bem em algum momento do passado), uma das minhas perguntas começou a levar mais de 7 segundos, em vez de milissegundos para executar. Eu tenho 1 tabela local e 3 tabelas sendo acessadas por meio de um link de banco de dados. As três tabelas remotas são unidas e uma delas é unida à minha mesa local.

A tabela local é que a cláusula leva apenas alguns milis para executar por conta própria e retorna apenas alguns registros (10 ou 100 no máximo). As três tabelas remotas têm muitas centenas de milhares, possivelmente milhões, de registros entre elas, e se eu me juntar a elas adequadamente, recebo dezenas ou centenas de milhares de registros.

Estou apenas juntando -me às tabelas remotas para que eu possa retirar alguns dados relacionados a cada registro na minha tabela local.

O que parece estar acontecendo, no entanto, é que o Oracle se junta às tabelas remotas primeiro e depois minha mesa local para essa bagunça no final. Isso sempre será uma má idéia, especialmente devido ao conjunto de dados que existe agora, então eu adicionei um /*+ LEADING(local_tab remote_tab_1) */ Dica à minha consulta e agora retorna em milissegundos.

Eu comparei os planos de explicação e eles são quase idênticos, exceto por um único BUFFER SORT em uma das tabelas remotas.

Estou me perguntando o que pode fazer com que a Oracle aborde isso da maneira errada? É um problema de índice? O que devo procurar?

Foi útil?

Solução

Ao escolher um plano de execução, a Oracle estima os custos para os diferentes planos. Uma informação crucial para essa estimativa é a quantidade de linhas devolvidas de uma etapa do plano de execução. O Oracle tenta estimar aqueles que usam 'estatísticas', ou seja, informações sobre quantas linhas uma tabela contém, quantos valores diferentes uma coluna contém; Quão uniformemente esses valores são distribuídos.

Essas estatísticas são exatamente essas estatísticas e podem estar erradas, que é uma das razões mais importantes para julgamentos errôneos do Oracle Optimizer.

Portanto, reunir novas estatísticas, conforme descrito em um comentário, pode ajudar. Dê uma olhada na documentação nesse pacote dbms_stats. Existem muitas maneiras diferentes de chamar esse pacote.

Outras dicas

Um problema comum que encontrei é uma consulta que se junta a muitas mesas, onde as junções formam uma corrente de uma extremidade para outra, por exemplo:

SELECT *
FROM   tableA, tableB, tableC, tableD, tableE
WHERE  tableA.ID0 = :bind1
AND    tableA.ID1 = tableB.ID1
AND    tableB.ID2 = tableC.ID2
AND    tableC.ID3 = tableD.ID3
AND    tableD.ID4 = tableE.ID4
AND    tableE.ID5 = :bind2;

Observe como o otimizador pode optar por direcionar a consulta do Tablea (por exemplo, se o índice no ID0 for bem seletivo) ou da Tablee (se o índice no Tablee.id5 for mais seletivo).

As estatísticas sobre as tabelas podem causar a escolha entre esses dois planos de equilibrar em uma borda da faca; Um dia, está funcionando bem (dirigindo de tablea), no dia seguinte, novas estatísticas são reunidas e, de repente, o plano alternativo que dirige da Tablee tem um custo menor e é escolhido.

Nesta circunstância, adicionar uma dica líder é mão única Para cutucá -lo de volta ao plano original (ou seja, unidade de tablea) sem ditar muito para o otimizador (ou seja, ele não force o otimizador a escolher nenhum método de junção específico).

Você está fazendo otimização de consulta distribuída, e isso é uma fera complicada. Pode ser que as estatísticas da sua tabela estejam atuais, mas agora as tabelas no sistema remoto estão fora de whack ou foram alteradas. Ou o sistema remoto adicionou/removeu/removido/modificado, e isso quebrou seu plano. (Este é um excelente motivo para considerar a replicação - para que você possa controlar índices e estatísticas contra ela.)

Dito isto, a estimativa da cardinalidade da Oracle é um motorista principal no plano de execução. Uma análise de rastreamento de 10053 (o livro dos fundamentos do Oracle Fundamentals, baseado em custos de Jonathan Lewis, tem exemplos maravilhosos de 8i a 10.1) pode ajudar a esclarecer por que sua declaração está quebrada e como o LEADING Dica conserta isso.

o DRIVING_SITE A dica pode ser uma escolha melhor se você souber que sempre deseja que as tabelas locais sejam unidas antes de ir atrás do site remoto; esclarece sua intenção sem dirigir o plano da maneira como um LEADING dica faria.

Pode não ser relevante, mas eu tive uma situação semelhante uma vez em que a tabela remota foi substituída por uma visualização de mesa única. Quando era uma tabela, o otimizador de consulta distribuído 'serra' que tinha um índice. Quando se tornou uma visão, não conseguia mais ver o índice e não podia custar um plano que usava um índice no objeto remoto.

Isso foi alguns anos atrás. Eu documentei minha análise na época aqui.

Ri,

É difícil ter certeza da causa dos problemas de desempenho sem ver o SQL.

Quando uma consulta do Oracle estava tendo um desempenho bem antes e de repente começa a ter um desempenho ruim, geralmente está relacionado a uma das duas questões:

A) As estatísticas estão desatualizadas. Essa é a coisa mais fácil e rápida a verificar, mesmo que você tenha um processo de lote de limpeza que deve cuidar disso ... sempre verifique duas vezes.

B) Alteração do volume / padrão de dados.

No seu caso, a execução de uma consulta distribuída em vários bancos de dados dificulta o 10X para o Oracle gerenciar o desempenho entre eles. É possível colocar essas tabelas em um banco de dados, talvez proprietários de esquemas separados em um banco de dados?

Dicas são notoriamente frágeis, pois o Oracle não tem obrigações de seguir a dica. Quando o volume de dados ou o padrão muda um pouco mais, o Oracle pode simplesmente ignorar a dica e fazer o que acha que é melhor (ou seja, pior ;-).

Se você não pode colocar essas tabelas em um banco de dados, recomendo que você procure dividir sua consulta em duas declarações:

  1. Insira no subselito para copiar dados externos para uma tabela temporária global no seu banco de dados atual.
  2. Selecione na tabela temporária global para participar da sua outra tabela.

Você terá controle completo sobre o desempenho da etapa 1 acima, sem recorrer a dicas. Essa abordagem normalmente escala bem, desde que você reserve um tempo para fazer o ajuste do desempenho. Eu já vi essa abordagem resolver muitos problemas complexos de desempenho.

A sobrecarga para o Oracle criar uma tabela totalmente nova ou inserir um monte de registros é muito menor do que a maioria das pessoas espera. Definir uma tabela temporária global reduz ainda mais essa sobrecarga.

Mateus

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top