[oracle_br] Re: Plano diferente quando usa bind

2009-05-29 Por tôpico jlchiappa
Ok, provavelmente então a suposição sobre a(s) coluna(s) do WHERE serem de 
distribuição altamente irregular, haver histogramas (E que são altamente 
necessários por causa da irregularidade) , e o plano ser gerado contra um valor 
não-significativo por conta do bind variable peeking deve ser isso mesmo 
Sim, uma das opções nos bancos antes do 11 é mesmo essa, forçar um PARSE a cada 
execução (com SQL dinâmico é uma opção), se te resolveu para esse ponto blz, só 
aconselho vc a ser proativo, e ** LEVANTAR ** quais pontos mais do 
sistema/quais SQLs mais mexem com colunas com dados de distribuição irregular, 
esses caras podem te aparecer no futuro...
  Quanto ao parâmetro, se NÂO tem nem documentação nem indicação de 
fornecedor/programador recomendando ter, CERTAMENTE não tem também nada 
recomendando não ter, então se eu fosse vc e fosse responsável pela bagaça, 
marcaria uma data pra alterar e ** TESTAR ** o banco com esse param setado tal 
como recomendado (ie, mesma versão do banco), pois com esse cara inferior  
MUITAS  melhorias introduzidas no 9i vc não está usando, vc PODE muito bem 
estar com performance / usabilidade inferiores à toa...

[]s

  Chiappa
--- Em oracle_br@yahoogrupos.com.br, Julio Bittencourt  
escreveu
>
> 
> 
> Chiappa, Gleyson,
> 
> Valeu pelas dicas. Fiz uma experiencia com execute immediate e deu certo! Os 
> planos de execução ficaram iguais aos da execução "por fora". A performance 
> ficou muito boa. Já passei as instruções para os desenvolvedores para 
> implementação (de quebra ainda descobri uma falha na lógica da procedure que 
> faz com que a query mais pesada seja exeuctada mais de uma vez, ninguém 
> merece...)
> 
> Essa procedure não é usada massivamente, só alguns poucos usuários a utilizam 
> e não é todo dia, então acredito que não irá impactar muito a shared pool. 
> Ficarei monitorando.
> 
> 
> Chiappa,
> Quanto ao parâmetro, eu até tentei descobrir o motivo, falei com várias 
> pessoas aqui e ninguém soube responder. Também não encontrei documentação a 
> respeito. Pelo que consegui descobrir, o banco era 8i e foi migrado para o 9. 
> Acho que nessa migração é que resolveram manter o compatible=816. Parece que 
> simplesmente a informação se perdeu, houve muita mudança de pessoal e quem 
> participou disso já se foi há muito tempo.
> Abçs.
> 
> De: oracle_br@yahoogrupos.com.br
> [mailto:oracle...@yahoogrupos.com.br] Em nome de jlchiappa
> 
> Enviada em: segunda-feira, 25 de maio de 2009 22:36
> 
> Para: oracle_br@yahoogrupos.com.br
> 
> Assunto: [oracle_br] Re: Plano diferente quando usa bind
> 
>  
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> Seguem algumas respostas, mas antes uma
> observação : quando vc diz que não sabe quem/por que setou esse parâmetro de
> compatibility , PRIMEIRO DE TUDO se vc vai ser responsável por esse ambiente,
> descubra o porquê : imho é ABSOLUTAMENTE crítico o DBA conhecer EXATAMENTE o
> ambiente aonde vai trabalhar, naõ importa que outra pessoa e não vc setou -
> abra chamado no Suporte do fornecedor da aplicação, faça (junto com os
> Analistas) testes sem o talzinho, mas DESCUBRA o porque, parâmetros do tipo
> PRECISAM de uma razão MUITO BOA pra serem setados...
> 
> 
> 
> Isto posto, as respostas: 
> 
> 
> 
> "Porque o Oracle não usa o mesmo plano de execução quando o select tem
> 
> bind e quando tem valores fixos?" : o que acontece é que quando vc informa
> o valor diretamente o banco TEM a possibilidade de consultar a distribuição 
> dos
> dados, de saber EXATAMENTE quantos registros distintos um WHERE filtra pro
> valor (isso é mantido num elemento chamado HISTOGRAMA das estatísticas de 
> CBO),
> já quando vc usa BIND VARIABLEs ele NÃO faz essa consulta a cada execução, mas
> só na primeira - isso porque há um overhead para se checar histogramas, que
> poderia ser inaceitável se simplesmente fosse ativado a cada SQL, cegamente.
> Isso pode, claro, levar a diferenças gritantes quando se usa bind, tanto se
> houver histogramas numa coluna não-apropriada quanto (o que parece ser o seu
> caso) os histogramas estão presentes mas não são usados devido à re-execução 
> de
> SQL com binds. Isso faz sentido, já que o objetivo de se usar BINDs é
> reaproveitar o mesmo SQL que será executado n vezes (tipicamente em OLTP),
> aonde é comum pesquisa indexada em SQLs relativamente simples (mas
> re-executados frequentemente), assim a distribuição é regular em
> princípio, os histogramas nem deveriam existir, mesmo Histogramas servem
> para vc mudar a presunção do CBO, de que a distribuição é regular, ie, se vc
> tem (digamos) 10 valores distintos no campo e 1000 registros, qquer filtro no
> WHERE por esse campo trará 1000/10 REGISTROS, é isso
> 
>

[oracle_br] Re: Plano diferente quando usa bind

2009-05-28 Por tôpico Julio Bittencourt


Chiappa, Gleyson,

Valeu pelas dicas. Fiz uma experiencia com execute immediate e deu certo! Os 
planos de execução ficaram iguais aos da execução "por fora". A performance 
ficou muito boa. Já passei as instruções para os desenvolvedores para 
implementação (de quebra ainda descobri uma falha na lógica da procedure que 
faz com que a query mais pesada seja exeuctada mais de uma vez, ninguém 
merece...)

Essa procedure não é usada massivamente, só alguns poucos usuários a utilizam e 
não é todo dia, então acredito que não irá impactar muito a shared pool. 
Ficarei monitorando.


Chiappa,
Quanto ao parâmetro, eu até tentei descobrir o motivo, falei com várias pessoas 
aqui e ninguém soube responder. Também não encontrei documentação a respeito. 
Pelo que consegui descobrir, o banco era 8i e foi migrado para o 9. Acho que 
nessa migração é que resolveram manter o compatible=816. Parece que 
simplesmente a informação se perdeu, houve muita mudança de pessoal e quem 
participou disso já se foi há muito tempo.
Abçs.

De: oracle_br@yahoogrupos.com.br
[mailto:oracle...@yahoogrupos.com.br] Em nome de jlchiappa

Enviada em: segunda-feira, 25 de maio de 2009 22:36

Para: oracle_br@yahoogrupos.com.br

Assunto: [oracle_br] Re: Plano diferente quando usa bind

 











Seguem algumas respostas, mas antes uma
observação : quando vc diz que não sabe quem/por que setou esse parâmetro de
compatibility , PRIMEIRO DE TUDO se vc vai ser responsável por esse ambiente,
descubra o porquê : imho é ABSOLUTAMENTE crítico o DBA conhecer EXATAMENTE o
ambiente aonde vai trabalhar, naõ importa que outra pessoa e não vc setou -
abra chamado no Suporte do fornecedor da aplicação, faça (junto com os
Analistas) testes sem o talzinho, mas DESCUBRA o porque, parâmetros do tipo
PRECISAM de uma razão MUITO BOA pra serem setados...



Isto posto, as respostas: 



"Porque o Oracle não usa o mesmo plano de execução quando o select tem

bind e quando tem valores fixos?" : o que acontece é que quando vc informa
o valor diretamente o banco TEM a possibilidade de consultar a distribuição dos
dados, de saber EXATAMENTE quantos registros distintos um WHERE filtra pro
valor (isso é mantido num elemento chamado HISTOGRAMA das estatísticas de CBO),
já quando vc usa BIND VARIABLEs ele NÃO faz essa consulta a cada execução, mas
só na primeira - isso porque há um overhead para se checar histogramas, que
poderia ser inaceitável se simplesmente fosse ativado a cada SQL, cegamente.
Isso pode, claro, levar a diferenças gritantes quando se usa bind, tanto se
houver histogramas numa coluna não-apropriada quanto (o que parece ser o seu
caso) os histogramas estão presentes mas não são usados devido à re-execução de
SQL com binds. Isso faz sentido, já que o objetivo de se usar BINDs é
reaproveitar o mesmo SQL que será executado n vezes (tipicamente em OLTP),
aonde é comum pesquisa indexada em SQLs relativamente simples (mas
re-executados frequentemente), assim a distribuição é regular em
princípio, os histogramas nem deveriam existir, mesmo Histogramas servem
para vc mudar a presunção do CBO, de que a distribuição é regular, ie, se vc
tem (digamos) 10 valores distintos no campo e 1000 registros, qquer filtro no
WHERE por esse campo trará 1000/10 REGISTROS, é isso



No seu caso, se usando o literal direto a performance é melhor, muito
certamente vc DEVE ter uma distribuição irregular na(s) coluna(s) em filtro e o
CBO está usando os histogramas, que são benéficos no seu caso, E a diferença
quando vc usa BIND é que com binds os histogramas só são consultados em tempo
de parse... Sendo assim, acho que a sua solução NÃO É o bind peek (que como eu
falei no artigo ele DESLIGA TOTALMENTE a busca por histogramas com bind
variables !!), o que vai ser RUIM pra performance de acordo com a suposição
acima, o que vc quer é o *** CONTRÁRIO ***, é justamente que ele use SEMPRE os
histogramas No banco 11i isso já foi mudado (e ficou mais
"esperto") mas no 9i e 10g vc vai ter que aplicar work-arounds na sua
programação, mas antes de discutir eu proponho que vc faça um TESTE pra provar
que é isso. Seria assim : faça uma pequena alteração no texto do SQL da tal
procedure com o bind (adicionando uma coluna a mais ou removendo coluna no
SELECT, botando um comentário, enfim, faça o SQL ficar diferente do que já está
no cache), aí execute a procedure passando pro bind EXATAMENTE O MESMO valor
que vc usou no teste sem binds que deu boa performance, como o texto é
diferente o banco não vai reusar o SQL anterior e vai recompilar e repesquisar
os histogramas, o que deve dar a mesma performance...

Se o teste resultar positivo, para vc fazer o SQL usar sempre histogramas, vc
tem as seguintes possibilidades :



a) simplesmente não use binds nesse SQL : prum SQL ser sensível a histogramas,
tipicamente ele não é OLTP (que se caracteriza por busca indexada como método
preferido), então é SIM possível e mesmo recomendável não usar BIND nesse caso


[oracle_br] Re: Plano diferente quando usa bind

2009-05-26 Por tôpico Julio Bittencourt
Fala Gleyson,

Sua sugestão bate com uma das que o Chiappa fez, então vou testar e dou um 
retorno.

Valeu!










De: oracle_br@yahoogrupos.com.br
[mailto:oracle...@yahoogrupos.com.br] Em nome de Gleyson Melo

Enviada em: segunda-feira, 25 de maio de 2009 20:29

Para: oracle_br@yahoogrupos.com.br

Assunto: Re: [oracle_br] Plano diferente quando usa bind











Fala Julio,

Se você colocar os valores como constantes nas consultas, o Oracle vai fazer

o uso de histogramas para verificar a distribuição das colunas e escolher o

melhor plano de execução que ele puder com base nisso.



Creio que seja esse o problema. Quantas vezes você chama esse SELECT?



As vantagens de você usar binds são reaproveitar planos de execução e

diminuir a concorrência na Shared Pool. Se você não ficar muito
"incomodado"

com um uso imperfeito da Shared Pool, você pode substituir colocar esse

SELECT dentro de um execute immediate e concatenar os valores que seriam

filtrados através de binds. Assim você força o Oracle a escolher um novo

plano de execução adequado para esse caso específico.



Se você postar a consulta, os planos (com e sem bind), índices e histogramas

da tabela, poderemos te ajudar mais.



Abraços.



2009/5/25 Julio Bittencourt 



>

>

> Temos um procedimento aqui que está demorando muito para executar.

> Após gerar um trace com "set events '10046" e analisá-lo, vi que
há três

> selects que consomem a maior parte do tempo.

>

> Peguei cada SELECT e os respectivos valores das variáveis bind e executei

> individualmente.

> Aí fica muito mais rápido, tipo se no procedimento cada um leva um minuto,

> individualmente leva menos de 10, isso quando os blocos ainda não estão no

> cache, se rodar de novo leva 1,5 segundos.

>

> Verifiquei que os planos de execução dos SQLs quando da execução pelo

> procedimento são diferentes de quando os executo individualmente com
valores

> fixos no lugar das variáveis bind.

>

> Então fiz um teste: Criei um procedimento de teste a partir do original,

> substituindo as variáveis pelos valores fixos e, como esperava, o tempo da

> execução caiu drasticamente.

> Isso indica que o Oracle está usando planos inadequados durante a execução

> do procedimento, mas não sei como fazer com que passe a utilizar planos

> melhores.

>

> Vi um artigo do Chiappa que fala sobre Bind Variable Peeking e tentei usar

> ALTER SESSION SET "_optim_peek_user_binds"=FALSE; ,
mas não surtiu efeito.

>

> Em resumo: Porque o Oracle não usa o mesmo plano de execução quando o

> select tem bind e quando tem valores fixos?

> O que posso fazer para forçá-lo a usar o mesmo plano?

>

> Dados do Servidor:

> Oracle 9.2.0.7 64 bits + Sun Solaris 9

> Detalhe: COMPATIBLE = 8.1.6 (não me perguntem porque, pois quando eu

> cheguei já estava assim e não posso mudar por enquanto)

>

> Agradeço desde já qualquer ajuda.

> Att.

> Julio

>

> Veja quais são os assuntos do momento no Yahoo! +Buscados

> http://br.maisbuscados.yahoo.com

>

> [As partes desta mensagem que não continham texto foram removidas]

>

> 

>



-- 

Atenciosamente,

Gleyson Melo

Oracle Database 10g Administrator Certified Professional



[As partes desta mensagem que não continham texto foram removidas]







  Veja quais são os assuntos do momento no Yahoo! +Buscados
http://br.maisbuscados.yahoo.com

[As partes desta mensagem que não continham texto foram removidas]



[oracle_br] Re: Plano diferente quando usa bind

2009-05-25 Por tôpico jlchiappa
Seguem algumas respostas, mas antes uma observação : quando vc diz que não sabe 
quem/por que setou esse parâmetro de compatibility , PRIMEIRO DE TUDO se vc vai 
ser responsável por esse ambiente, descubra o porquê : imho é ABSOLUTAMENTE 
crítico o DBA conhecer EXATAMENTE o ambiente aonde vai trabalhar, naõ importa 
que outra pessoa e não vc setou - abra chamado no Suporte do fornecedor da 
aplicação, faça (junto com os Analistas) testes sem o talzinho, mas DESCUBRA o 
porque, parâmetros do tipo PRECISAM de uma razão MUITO BOA pra serem setados...

Isto posto, as respostas: 
 
 "Porque o Oracle não usa o mesmo plano de execução quando o select tem
bind e quando tem valores fixos?" : o que acontece é que quando vc informa o 
valor diretamente o banco TEM a possibilidade de consultar a distribuição dos 
dados, de saber EXATAMENTE quantos registros distintos um WHERE filtra pro 
valor (isso é mantido num elemento chamado HISTOGRAMA das estatísticas de CBO), 
já quando vc usa BIND VARIABLEs ele NÃO faz essa consulta a cada execução, mas 
só na primeira - isso porque há um overhead para se checar histogramas, que 
poderia ser inaceitável se simplesmente fosse ativado a cada SQL, cegamente. 
Isso pode, claro, levar a diferenças gritantes quando se usa bind, tanto se 
houver histogramas numa coluna não-apropriada quanto (o que parece ser o seu 
caso) os histogramas estão presentes mas não são usados devido à re-execução de 
SQL com binds.Isso faz sentido, já que o objetivo de se usar BINDs é 
reaproveitar o mesmo SQL que será executado n vezes (tipicamente em OLTP), 
aonde é comum pesquisa indexada em SQLs relativamente simples (mas 
re-executados frequentemente), assim a distribuição é regular em princípio, os 
histogramas nem deveriam existir, mesmo  Histogramas servem para vc mudar a 
presunção do CBO, de que a distribuição é regular, ie, se vc tem (digamos) 10 
valores distintos no campo e 1000 registros, qquer filtro no WHERE por esse 
campo trará 1000/10 REGISTROS, é isso

 No seu caso, se usando o literal direto a performance é melhor, muito 
certamente vc DEVE ter uma distribuição irregular na(s) coluna(s) em filtro e o 
CBO está usando os histogramas, que são benéficos no seu caso, E a diferença 
quando vc usa BIND é que com binds os histogramas só são consultados em tempo 
de parse... Sendo assim, acho que a sua solução NÃO É o bind peek (que como eu 
falei no artigo ele DESLIGA TOTALMENTE a busca por histogramas com bind 
variables !!), o que vai ser RUIM pra performance de acordo com a suposição 
acima, o que vc quer é o *** CONTRÁRIO ***, é justamente que ele use SEMPRE os 
histogramas No banco 11i isso já foi mudado (e ficou mais "esperto") mas no 
9i e 10g vc vai ter que aplicar work-arounds na sua programação, mas antes de 
discutir eu proponho que vc faça um TESTE pra provar que é isso. Seria assim : 
faça uma pequena alteração no texto do SQL da tal procedure com o bind 
(adicionando uma coluna a mais ou removendo coluna no SELECT, botando um 
comentário, enfim, faça o SQL ficar diferente do que já está no cache), aí 
execute a procedure passando pro bind EXATAMENTE O MESMO valor que vc usou no 
teste sem binds que deu boa performance, como o texto é diferente o banco não 
vai reusar o SQL anterior e vai recompilar e repesquisar os histogramas, o que 
deve dar a mesma performance...
   Se o teste resultar positivo, para vc fazer o SQL usar sempre histogramas, 
vc tem as seguintes possibilidades :
   
   a) simplesmente não use binds nesse SQL : prum SQL ser sensível a 
histogramas, tipicamente ele não é OLTP (que se caracteriza por busca indexada 
como método preferido), então é SIM possível e mesmo recomendável não usar BIND 
nesse caso
  
   b) se vc conseguir descobrir quais valores estão dando má-performance com 
BINDs, e eles forem poucos e previsíveis, vc fazer uma programação específica 
pra eles, tipo :
 IF condição ruim then
SELECT com valores fixos
 ELSE
SELECT com binds

  tipo assim
  
   c) forçar hard parse a cada execução do SQL em questão : por exemplo, vc 
poderia usar SQL dinâmico (isso necessariamente causa um hard parse e portanto 
uma pesquisa nos histogramas), ou vc poderia fazer (via EXECUTE IMMEDIATE, 
talvez) uma alteração inócua numa das tabelas , normalmente quando os objetos 
envolvidos mudam um hard parse é inevitável
   
   []s
   
 Chiappa
--- Em oracle_br@yahoogrupos.com.br, Julio Bittencourt  
escreveu
>
> Temos um procedimento aqui que está demorando muito para executar. 
> Após gerar um trace com "set events '10046" e analisá-lo, vi que há três 
> selects que consomem a maior parte do tempo.
>  
> Peguei cada SELECT e os respectivos valores das variáveis bind e executei 
> individualmente. 
> Aí fica muito mais rápido, tipo se no procedimento cada um leva um minuto, 
> individualmente leva menos de 10, isso quando os blocos ainda não estão no 
> cache, se rodar de novo leva 1,5 segundos.
>  
> Veri