Dica líder da Oracle - por que isso é necessário?
-
22-09-2019 - |
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?
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:
- Insira no subselito para copiar dados externos para uma tabela temporária global no seu banco de dados atual.
- 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