Por que o SQL Server não faz histogramas estatísticos de coluna composta?

10

O SQL Server tem uma coisa chamada "estatísticas de várias colunas", mas não é o que se pensa.

Vamos dar uma olhada na seguinte tabela de exemplo:

CREATE TABLE BadStatistics 
(
    IsArchived BIT NOT NULL,
    Id INT NOT NULL IDENTITY PRIMARY KEY,
    Mystery VARCHAR(200) NOT NULL
);

CREATE NONCLUSTERED INDEX BadIndex 
    ON BadStatistics (IsArchived, Mystery);

Com isso, duas estatísticas estão sendo criadas nos dois índices que temos:

Estatísticas para BadIndex:

+--------------+----------------+-------------------------+
| All density  | Average Length | Columns                 |
+--------------+----------------+-------------------------+
| 0.5          | 1              | IsArchived              |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 37             | IsArchived, Mystery     |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 41             | IsArchived, Mystery, Id |
+--------------+----------------+-------------------------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 0            | 0          | 24398   | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 216602  | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

Estatísticas para o índice em cluster:

+--------------+----------------+---------+
| All density  | Average Length | Columns |
+--------------+----------------+---------+
| 4.149378E-06 | 4              | Id      |
+--------------+----------------+---------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 240999       | 240997     | 1       | 240997              | 1              |
+--------------+------------+---------+---------------------+----------------+
| 241000       | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

(Preenchi a tabela com dados de amostra aleatórios, nos quais cerca de um décimo das linhas não são arquivadas. Fiz uma atualização completa das estatísticas da verificação posteriormente.)

Por que o histograma das estatísticas de duas colunas usa apenas uma coluna? Eu sei que muitas pessoas têm escrito sobre que faz , mas o que é a razão? Nesse caso, torna todo o histograma muito menos útil, porque a primeira coluna possui apenas dois valores. Por que as estatísticas seriam arbitrariamente restritas assim?

Observe que esta pergunta não se refere a histogramas multidimensionais, que são uma fera totalmente diferente. Trata-se de histogramas unidimensionais, com a dimensão única sendo as tuplas contendo as respectivas colunas múltiplas.

John
fonte

Respostas:

8

fundo

O modelo atual do SQL Server usa apenas histogramas de coluna única e informações de densidade de várias colunas. Os histogramas de coluna única são usados ​​para estimar a seletividade para predicados adequados, por exemplo, a = 1ou b > 50. Uma consulta com vários predicados simplesmente combina as seletividades individuais (com suposições) para produzir uma seletividade geral estimada.

Por exemplo, consulte o meu artigo Estimativa de cardinalidade: combinando estatísticas de densidade

A densidade de várias colunas informa ainda mais o modelo, fornecendo informações de correlação fracas para vários predicados de igualdade e cardinalidades de agrupamento para agregações.

As estatísticas associadas aos índices são um complemento oportunista para esse modelo: O mecanismo também pode coletar estatísticas (normalmente varredura completa) enquanto está construindo um índice. O SQL Server cria automaticamente um histograma da coluna principal e informações de densidade para as outras chaves.

Os histogramas para colunas não principais em um índice podem ser construídos sob demanda automaticamente pelo processador de consultas ou com antecedência usando sp_createstatsa @indexonlyopção (entre outros).

Histogramas de várias colunas

As suposições feitas ao combinar estatísticas de coluna única (como acima) podem ou não modelar a realidade dos dados suficientemente bem. Em muitos casos, as opções disponíveis (retirada exponencial, independência, seletividade mínima) produzem uma estimativa 'boa o suficiente'.

Também filtramos estatísticas (e índices) como uma solução natural para índices de colunas principais de baixa cardinalidade, como no exemplo da pergunta. Levá-los ao extremo lógico nos aproxima mais das estatísticas multidimensionais das quais a questão não se refere.

Quando as opções de modelagem disponíveis não podem fornecer uma estimativa adequada, um histograma estatístico de várias colunas poderia realmente fornecer uma estimativa de seletividade melhor para predicados de índice adequados, em alguns casos. Existem algumas dificuldades em combinar diferentes tipos de dados em colunas diferentes, mas nada insuperável.

Também precisaríamos de um histograma para cada nível das chaves de índice (para obter melhores resultados); portanto, para um índice, (a, b, c)isso significaria histogramas (a, b)e (a, b, c), além do atual histograma de coluna única, (a)sozinho.

O mecanismo usado para detectar estatísticas obsoletas também precisaria ser modificado para manter os histogramas de várias colunas afetados. Esses histogramas provavelmente acabariam sendo reconstruídos com mais frequência do que as estatísticas de coluna única, simplesmente porque modificações em mais colunas os afetam.

Tudo isso adiciona tamanho, complexidade e sobrecarga de manutenção.

As estatísticas de várias colunas podem ser simuladas (até um limite limitado) usando uma estatística criada em uma coluna computada cuidadosamente construída, referenciando várias colunas. A consulta precisaria incluir um predicado na coluna computada (ou uma correspondência textual exata para a fórmula subjacente) para tirar proveito dessa estatística. Provavelmente, existem apenas situações muito limitadas em que essa abordagem é prática. No entanto, ele tem alguns dos mesmos problemas de implementação que os histogramas automáticos de várias colunas teriam.

Por fim, as únicas pessoas que poderiam dizer com certeza por que o SQL Server não oferece suporte a estatísticas de várias colunas seriam os próprios designers. Se você acha que pode defender uma melhoria de produto nesta área com ampla aplicabilidade, sugeri-lo no Connect ou através do seu canal de suporte normal.

Nota de rodapé

Nesse caso, torna todo o histograma muito menos útil, porque a primeira coluna possui apenas dois valores

O histograma ainda fornece informações úteis sobre a distribuição de valores na coluna principal: Quando as estatísticas foram construídas, havia 24.398 linhas onde IsArchivedera falso e 216.602 linhas onde era verdade .

Além disso, o objeto de estatísticas nos diz que existem (1 / 0,5) = 2 valores distintos para IsArchived, (1 / 4.149378E-06) ~ = 241000 valores distintos para (IsArchived, Mystery)um tamanho de linha médio de 37 bytes e a mesma frequência para (IsArchived, Mystery, Id)com 4 bytes extras por linha.

Todas essas informações são boas para uso geral, que podem ser combinadas com informações estatísticas sobre outras colunas para produzir uma estimativa de seletividade em consultas com vários predicados (como mencionado).

Paul White 9
fonte