Márcio, eu li a entrada sobre SIZE do seu blog e tenho um item a adicionar, vou faze-lo aqui pra que mais gente se eventualmente se beneficie. É o seguinte, quando vc não informa o SIZE, ** não ** é sempre que o "Oracle faz o trabalho" - o que ocorre é que, SE o número de valores distintos for nitidamente menor que o número de buckets mínimo do banco (por volta de uns 70), isso funciona bem, mas se não for isso, vc pode ter problemas. Exemplo :
Conectado a: Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options JServer Release 9.2.0.5.0 - Production [EMAIL PROTECTED]:SQL>create table TEST (n1 number not null); Tabela criada. ==> vamos ter apenas 4 valores distintos, pra início [EMAIL PROTECTED]:SQL>BEGIN 2 FOR I IN 1..5 LOOP 3 INSERT INTO TEST (SELECT I FROM ALL_OBJECTS WHERE ROWNUM < I*I); 4 COMMIT; 5 END LOOP; 6 END; 7 / Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>exec dbms_stats.gather_table_stats(user, 'TEST', cascade =>TRUE, method_opt=>'for columns n1'); Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>select count(*) from user_histograms where table_name='TEST'; COUNT(*) ------------------ 4 [EMAIL PROTECTED]:SQL>SELECT COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE, DENSITY, NUM_NULLS, NUM_BUCKETS, SAMPLE_SIZE FROM USER_TAB_COLUMNS WHERE TABLE_NAME='TEST'; COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ------------------------------ ------------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ ------------------ ------------------ ------------------ N1 4 C103 C106 ,01 0 3 50 [EMAIL PROTECTED]:SQL>SELECT MIN(N1), DUMP(MIN(N1), 16) , MAX(N1), DUMP(MAX(N1), 16) FROM TEST; [EMAIL PROTECTED]:SQL>/ MIN(N1) ------------------ DUMP(MIN(N1),16) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MAX(N1) ------------------ DUMP(MAX(N1),16) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 2 Typ=2 Len=2: c1,3 5 Typ=2 Len=2: c1,6 ==> ok, vamos usar : [EMAIL PROTECTED]:SQL>set autotrace traceonly; [EMAIL PROTECTED]:SQL>select * from test where n1=3; 8 linhas selecionadas. Plano de Execução ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=8 Bytes=24) 1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=2 Card=8 Bytes=24) Estatística ---------------------------------------------------------- 0 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 443 bytes sent via SQL*Net to client 499 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 8 rows processed [EMAIL PROTECTED]:SQL>set autotrace off ==> vamos recoletar com size maior : [EMAIL PROTECTED]:SQL>exec dbms_stats.gather_table_stats(user, 'TEST', cascade =>TRUE, method_opt=>'for columns n1 size 5'); Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>select count(*) from user_histograms where table_name='TEST'; COUNT(*) ------------------ 4 [EMAIL PROTECTED]:SQL>SELECT COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE, DENSITY, NUM_NULLS, NUM_BUCKETS, SAMPLE_SIZE FROM USER_TAB_COLUMNS WHERE TABLE_NAME='TEST'; COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ------------------------------ ------------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ ------------------ ------------------ ------------------ N1 4 C103 C106 ,229230769230769 0 3 50 [EMAIL PROTECTED]:SQL>set autotrace traceonly [EMAIL PROTECTED]:SQL>select * from test where n1=3; 8 linhas selecionadas. Plano de Execução ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=11 Bytes=33) 1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=2 Card=11 Bytes=33) Estatística ---------------------------------------------------------- 0 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 443 bytes sent via SQL*Net to client 499 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 8 rows processed ==> cardinalidade passou de 8 pra 11, é ruído, diferença tão pequena que é desprezível, teste IGUAIS na prática. AGORA vamos ter mais valores distintos... [EMAIL PROTECTED]:SQL>set autotrace off [EMAIL PROTECTED]:SQL>truncate table test; Tabela truncada. [EMAIL PROTECTED]:SQL>BEGIN 2 FOR I IN 1..125 LOOP 3 INSERT INTO TEST (SELECT I FROM ALL_OBJECTS WHERE ROWNUM < I*I); 4 COMMIT; 5 END LOOP; 6 END; 7 / Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>SELECT MIN(N1), DUMP(MIN(N1), 16) , MAX(N1), DUMP(MAX(N1), 16) FROM TEST; MIN(N1) ------------------ DUMP(MIN(N1),16) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MAX(N1) ------------------ DUMP(MAX(N1),16) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 2 Typ=2 Len=2: c1,3 125 Typ=2 Len=3: c2,2,1a ==> primeiro vamos coletar como vc sugeriu, sem informar bucket size : [EMAIL PROTECTED]:SQL>exec dbms_stats.gather_table_stats(user, 'TEST', cascade =>TRUE, method_opt=>'for columns n1'); Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>select count(*) from user_histograms where table_name='TEST'; COUNT(*) ------------------ 64 => ele fez o número mínimo de buckets - sempre há uma pequena variação porque o histograma que o Oracle usa é height-based (por "altura"), isto é, ele sempre quer a mesmo quantidade de valores distintos em cada "caixa", mais 1 ou menos 1... [EMAIL PROTECTED]:SQL>SELECT COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE, DENSITY, NUM_NULLS, NUM_BUCKETS, SAMPLE_SIZE FROM USER_TAB_COLUMNS WHERE TABLE_NAME='TEST'; COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ------------------------------ ------------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ ------------------ ------------------ ------------------ N1 124 C103 C2021A ,0122118731219246 0 63 658750 ==> atenção ao campo DENSITY acima... Vamos fazer uma query : [EMAIL PROTECTED]:SQL>set autotrace traceonly [EMAIL PROTECTED]:SQL>SELECT * FROM TEST WHERE N1=20; 399 linhas selecionadas. Plano de Execução ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=98 Card=8045 Bytes=32180) 1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=98 Card=8045 Bytes=32180) Estatística ---------------------------------------------------------- 0 recursive calls 0 db block gets 1032 consistent gets 491 physical reads 0 redo size 5571 bytes sent via SQL*Net to client 785 bytes received via SQL*Net from client 28 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 399 rows processed ==> humm, cardinalidade de 8405, tá. vamos agora ** indicar ** o número de buckets para ser mais próximo do valor real de distintos (qundo vc não informa o size, o bd Oracle ** não ** faz isso !!) : [EMAIL PROTECTED]:SQL>set autotrace off [EMAIL PROTECTED]:SQL>exec dbms_stats.gather_table_stats(user, 'TEST', cascade =>TRUE, method_opt=>'for columns n1 size 125'); Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>select count(*) from user_histograms where table_name='TEST'; COUNT(*) ------------------ 78 [EMAIL PROTECTED]:SQL>SELECT COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE, DENSITY, NUM_NULLS, NUM_BUCKETS, SAMPLE_SIZE FROM USER_TAB_COLUMNS WHERE TABLE_NAME='TEST'; COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ------------------------------ ------------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ ------------------ ------------------ ------------------ N1 124 C103 C2021A ,00747264610999656 0 77 658750 ==> humm, além de ter mais buckets, a DENSIDADE mudou (claro, os valores estão mais distribuídos, por mais "caixas"). ok, vamos usar : [EMAIL PROTECTED]:SQL>set autotrace traceonly [EMAIL PROTECTED]:SQL>SELECT * FROM TEST WHERE N1=20; 399 linhas selecionadas. Plano de Execução ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=98 Card=4923 Bytes=19692) 1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=98 Card=4923 Bytes=19692) Estatística ---------------------------------------------------------- 0 recursive calls 0 db block gets 1032 consistent gets 519 physical reads 0 redo size 5571 bytes sent via SQL*Net to client 785 bytes received via SQL*Net from client 28 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 399 rows processed ===>> SANTO VALOR , Batman!! A mesma query, com os MESMOS dados, mas a cardinalidade caiu quase pela METADE, de 8045 para 4923 !!! E é claro, sabemos nós que a CARDINALIDADE é um item-CHAVE pro CBO tomar decisões... Então, se isto fosse um JOIN, ** muito ** provavelmente o plano IRIA mudar !! veja só, a ** mesma ** query, com os ** mesmos ** dados, só por ter sido informado mais detalhadamente a info necessária, muda radicalmente... Antes que neguinho pergunte, só pra mostrar que não tem ** nada ** a ver com caches, ordem de execução, nada disso, faço de novo sem informar size : [EMAIL PROTECTED]:SQL>exec dbms_stats.gather_table_stats(user, 'TEST', cascade =>TRUE, method_opt=>'for columns n1'); Procedimento PL/SQL concluído com sucesso. [EMAIL PROTECTED]:SQL>select count(*) from user_histograms where table_name='TEST'; COUNT(*) ------------------ 64 [EMAIL PROTECTED]:SQL>SELECT COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE, DENSITY, NUM_NULLS, NUM_BUCKETS, SAMPLE_SIZE FROM USER_TAB_COLUMNS WHERE TABLE_NAME='TEST'; COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ------------------------------ ------------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ ------------------ ------------------ ------------------ N1 124 C103 C2021A ,0122118731219246 0 63 658750 [EMAIL PROTECTED]:SQL>set autotrace traceonly [EMAIL PROTECTED]:SQL>SELECT * FROM TEST WHERE N1=20; 399 linhas selecionadas. Plano de Execução ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=98 Card=8045 Bytes=32180) 1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=98 Card=8045 Bytes=32180) Estatística ---------------------------------------------------------- 0 recursive calls 0 db block gets 1032 consistent gets 576 physical reads 0 redo size 5571 bytes sent via SQL*Net to client 785 bytes received via SQL*Net from client 28 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 399 rows processed [EMAIL PROTECTED]:SQL> []s Chiappa --- Em oracle_br@yahoogrupos.com.br, "Marcio Portes" <[EMAIL PROTECTED]> escreveu > Escrevi outra notinha lá. > > http://mportes.blogspot.com/2005/11/histograma-definio-size.html > > Abraço, > > --- Em oracle_br@yahoogrupos.com.br, "Rosiano Vieira de Sales" > <[EMAIL PROTECTED]> escreveu > > Marcio... dei uma lida no seu blog a respeito e gostei muito da > nota que vc publicou ....contudo fiquei com uma dúvida ....qual o > critério para definir o size do historgrama ??? .... se tiver algo a > respeito envie para o grupo .. vai ser de muito proveito ..... > > > > abç. > > > > Rosiano > > > > -----Mensagem original----- > > De: oracle_br@yahoogrupos.com.br em nome de Marcio Portes > > Enviada: qua 23/11/2005 15:06 > > Para: oracle_br@yahoogrupos.com.br > > Cc: > > Assunto: [oracle_br] Re: Histogramas.???? > > > > > > > > Welvis, tomei a liberdade de escrever uma pequena > introdução para sua > > dúvida no meu blog. > > Se interessar: > > http://mportes.blogspot.com/2005/11/histograma-introduo.html > > > > abraços, > > > > --- Em oracle_br@yahoogrupos.com.br, Welvis Douglas Silva > Moreto > > <[EMAIL PROTECTED]> escreveu > > > Quando devo estar utilizando Histogramas.... quais > > > beneficios terei utilizando o. > > > > > > > > > att, > > > > > > Welvis Douglas > > > > > > > > > > > > > > > > > > > > > > > > > > > _______________________________________________________ > > > Yahoo! Acesso Grátis: Internet rápida e grátis. > > > Instale o discador agora! > > > http://br.acesso.yahoo.com/ > > > > > > > > > > > > -------------------------------------------------------------- > ------------------------------------------------------------ > > Atenção! As mensagens deste grupo são de acesso público e > de inteira responsabilidade de seus remetentes. > > Acesse: http://www.mail- > archive.com/oracle_br@yahoogrupos.com.br/ > > -------------------------------------------------------------- > ------------------------------------------------------------ > _____________________________________________________________________ > > Area de download do grupo - > http://www.4shared.com/dir/101727/a4dcc423 > > Links do Yahoo! Grupos > > > > > > > > > > > > > > > > > > > > > > > > [As partes desta mensagem que não continham texto foram removidas] -------------------------------------------------------------------------------------------------------------------------- Atenção! As mensagens deste grupo são de acesso público e de inteira responsabilidade de seus remetentes. Acesse: http://www.mail-archive.com/oracle_br@yahoogrupos.com.br/ --------------------------------------------------------------------------------------------------------------------------_____________________________________________________________________ Area de download do grupo - http://www.4shared.com/dir/101727/a4dcc423 Links do Yahoo! Grupos <*> Para visitar o site do seu grupo na web, acesse: http://br.groups.yahoo.com/group/oracle_br/ <*> Para sair deste grupo, envie um e-mail para: [EMAIL PROTECTED] <*> O uso que você faz do Yahoo! Grupos está sujeito aos: http://br.yahoo.com/info/utos.html