Coletar Estatísticas com ESTIMATE PERCENT 100% é pior

Muitos DBAs gostam de coletar estatísticas com ESTIMATE_PERCENT=>100, achando que isto é o melhor a ser feito.

Até o 11gR2 isto poderia ser apenas um desperdício de tempo e recursos durante a coleta. Mas a partir do 12cR1, isto passou a ser um problema.

Sobre o desperdício, na grande maioria das vezes a indicação do percentual é desnecessária: a partir do 11.2.0.4, o algoritmo utilizado quando se escolhe o percentual automático (DBMS_STATS.AUTO_SAMPLE_SIZE, que é o padrão) faz escolhas excelentes e coleta boas estatísticas, e dificilmente leva o CBO a tomar uma decisão errada. Esta melhoria provavelmente tem a ver com o uso de APPROX_COUNT_DISTINCT:

The APPROX_COUNT_DISTINCT function was added, but not documented, in Oracle 11g to improve the speed of calculating the number of distinct values (NDV) when gathering statistics using the DBMS_STATS package.
Fonte: https://oracle-base.com/articles/12c/approx-count-distinct-12cr1

Sobre o problema, a partir do 12cR1 o Oracle Database passou a ter mais dois tipos de Histogramas: o Top Frequency e o Hybrid, que são muito melhores do que o Height-Balanced (outra grande melhoria nos Histogramas é o limite maior de Buckets, de 254 para 2048). Geralmente quando se tem um problema com Histogramas, isto acontece por conta da distribuição feita pelo Height-Balanced. Uma boa parte da Lenda “Histogramas são ruins” deve-se aos Height Balanced.

Mas os novos tipos de Histogramas do 12c só são utilizados de o AUTO_SAMPLE_SIZE é utilizado. Se for indicado ESTIMATE_PERCENT, tanto de 1% quanto de 100%, os novos tipos não podem ser utilizados, e quando há mais valores distintos na coluna analisada do que o limite de Buckets, isto leva invariavelmente a um Histograma do famigerado Height Balanced.

08:34:54 SCOTT@PROD> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','T62');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.13
08:34:54 SCOTT@PROD> SELECT COLUMN_ID, COLUMN_NAME, HISTOGRAM FROM DBA_TAB_COLUMNS WHERE OWNER = 'SCOTT' AND TABLE_NAME = 'T62' ORDER BY COLUMN_ID;

 COLUMN_ID COLUMN_NAME					    HISTOGRAM
---------- ------------------------------------------------ ---------------
	 1 DATA_PEDIDO				            HYBRID

Elapsed: 00:00:00.00
08:34:57 SCOTT@PROD> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','T62', ESTIMATE_PERCENT=>100);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.23
08:35:00 SCOTT@PROD> SELECT COLUMN_ID, COLUMN_NAME, HISTOGRAM FROM DBA_TAB_COLUMNS WHERE OWNER = 'SCOTT' AND TABLE_NAME = 'T62' ORDER BY COLUMN_ID;

 COLUMN_ID COLUMN_NAME					   HISTOGRAM
---------- ----------------------------------------------- ---------------
	 1 DATA_PEDIDO					   HEIGHT BALANCED

Elapsed: 00:00:00.00
08:35:03 SCOTT@PROD> 

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

This site uses Akismet to reduce spam. Learn how your comment data is processed.