10.2. Estatísticas utilizadas pelo planejador

Conforme foi visto na seção anterior, o planejador de consultas precisa estimar o número de linhas encontradas pela consulta, para poder fazer boas escolhas dos planos de consulta. Esta seção fornece uma breve visão das estatísticas utilizadas pelo sistema para realizar estas estimativas.

Um dos componentes da estatística é o número total de entradas em cada tabela e índice, assim como o número de blocos de disco ocupados por cada tabela e índice. Esta informação é mantida nas colunas reltuples e relpages da tabela pg_class. Isto pode ser visto utilizando consultas semelhantes à mostrada abaixo:

regression=# SELECT relname, relkind, reltuples, relpages FROM pg_class
regression-# WHERE relname LIKE 'tenk1%';
    relname    | relkind | reltuples | relpages
---------------+---------+-----------+----------
 tenk1         | r       |     10000 |      233
 tenk1_hundred | i       |     10000 |       30
 tenk1_unique1 | i       |     10000 |       30
 tenk1_unique2 | i       |     10000 |       30
(4 rows)

Pode ser visto que tenk1 contém 10.000 linhas, assim como seus índices, mas que os índices são (sem surpresa) muito menores que a tabela.

Por razões de eficiência, as colunas reltuples e relpages não são atualizadas dinamicamente e, portanto, usualmente contêm valores aproximados apenas (que são suficientemente bons para as finalidades do planejador). Estas colunas são inicializadas com valores fictícios (atualmente 1.000 e 10, respectivamente) quando a tabela é criada. São atualizadas por alguns comandos, atualmente VACUUM, ANALYZE e CREATE INDEX. Um comando autônomo ANALYZE, que não faça parte do VACUUM, coloca um valor aproximado em reltuples porque não são lidas todas as linhas da tabela.

A maioria das consultas retorna apenas uma parte das linhas da tabela, devido à cláusula WHERE que restringe as linhas a ser examinadas. Portanto, o planejador precisa fazer uma estimativa da seletividade das cláusulas do WHERE, ou seja, a fração das linhas correspondendo a cada cláusula da condição WHERE. A informação utilizada para esta tarefa é armazenada no catálogo do sistema pg_statistic. As entradas em pg_statistic são atualizadas pelos comandos ANALYZE e VACUUM ANALYZE, sendo sempre aproximadas, mesmo logo após serem atualizadas.

Em vez de olhar pg_statistic diretamente, é melhor olhar sua visão pg_stats para examinar as estatísticas manualmente. A visão pg_stats é projetada para ser lida mais facilmente. Além disso, pg_stats pode ser lida por todos, enquanto pg_statistic somente pode ser lida pelo superusuário. (Isto impede que usuários não privilegiados obtenham informações relativas ao conteúdo da tabela de outras pessoas a partir de suas estatísticas. A visão pg_stats mostra somente linhas relativas às tabelas que o usuário corrente pode ler). Por exemplo, poderia ser executado:

regression=# SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road';
 attname | n_distinct |                                                                                                                                                                                  most_common_vals                                                                                                                                                                                   
---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 name    |  -0.467008 | {"I- 580                        Ramp","I- 880                        Ramp","Sp Railroad                       ","I- 580                            ","I- 680                        Ramp","I- 80                         Ramp","14th                          St  ","5th                           St  ","Mission                       Blvd","I- 880                            "}
 thepath |         20 | {"[(-122.089,37.71),(-122.0886,37.711)]"}
(2 rows)
regression=#

A Tabela 10-1 mostra as colunas existentes em pg_stats.

Tabela 10-1. Colunas da visão pg_stats

NomeTipoDescrição
tablenamenameNome da tabela contendo a coluna
attnamenameColuna descrita por esta linha
null_fracrealFração das entradas nulas na coluna
avg_widthintegerLargura média em bytes das entradas da coluna
n_distinctrealSe for maior que zero, o número estimado de valores distintos presentes na coluna. Se for menor que zero, o negativo do número de valores distintos dividido pelo número de linhas (A forma negativa é utilizada quando o ANALYZE acredita que o número de valores distintos possivelmente aumentará junto com o crescimento da tabela; a forma positiva é utilizada quando a coluna parece ter um número fixo de valores possíveis). Por exemplo, -1 indica uma coluna com restrição de unicidade onde o número de valores distintos é o mesmo que a quantidade de linhas.
most_common_valstext[]A lista dos valores mais comuns da coluna (Omitido se nenhum valor parece ser mais comum que os outros).
most_common_freqsreal[]A lista das freqüências dos valores mais comuns, ou seja, o número de ocorrências de cada um dividido pelo número total de linhas.
histogram_boundstext[]A lista dos valores que dividem os valores das colunas em grupos com populações aproximadamente iguais. Se most_common_vals existir, estes valores são omitidos no cálculo do histograma (Omitido se o tipo de dado da coluna não possui o operador <, ou se a lista most_common_vals for toda a população).
correlationrealCorrelação estatística entre a ordem física das linhas e a ordenação lógica dos valores da coluna. O intervalo é de -1 a +1. Quando o valor está próximo de -1 ou de +1, uma varredura de índice na coluna será estimada como sendo mais barata do que quando estiver próximo de zero, devido à redução de acessos aleatórios no disco (Omitido se o tipo de dado da coluna não possui o operador <).

O número máximo de entradas nas matrizes most_common_vals e histogram_bounds podem ser definidos coluna por coluna utilizando o comando ALTER TABLE SET STATISTICS. Atualmente, o limite padrão é de 10 entradas. Aumentar o valor pode permitir o planejador realizar estimativas mais precisas, em particular para colunas com distribuição de dados irregular, ao custo de consumir mais espaço em pg_statistic e um pouco mais de tempo para calcular as estimativas. Inversamente, um limite mais baixo pode ser apropriado para colunas com distribuição simples dos dados.