Estamos no processo de construção de um banco de dados para um novo aplicativo. Recebi alguns comentários do arquiteto de que ele leu em algum lugar que há um benefício de utilização de memória por ter todas as colunas não anuláveis em uma tabela primeiro, depois todas as colunas anuláveis. Se houver colunas anuláveis entre colunas não anuláveis, algum tipo de benefício de memória ou armazenamento será perdido porque essas colunas anuláveis estão entre colunas não anuláveis.
As colunas foram ordenadas em uma ordem ligeiramente ambígua, mas em geral foi priorizada para colunas que eram mais prováveis de serem usadas primeiro.
Fiquei com a impressão de que o SSMS ordena as colunas no arquivo de paginação por sua própria lógica, em vez da ordem específica em que são criadas na tabela. Que a ordem em que coloquei as colunas na tabela era totalmente independente de como os dados eram armazenados no arquivo de paginação.
Existe alguma documentação em algum lugar que apoiaria essa descoberta/compreensão?
EDITAR:
Ter mais algumas conversas sobre descobrir de onde veio essa ideia. A solicitação foi uma simplificação excessiva de ter alta densidade de dados ou colunas usadas com mais frequência SELECT
ou JOIN
operações na frente da tabela para impedir que eles fossem movidos para a seção Estouro do arquivo de página.
Que a ordem das colunas atribuídas à tabela seja a mesma ordem em que os dados são adicionados ao arquivo de paginação. Para uma determinada linha, os dados são armazenados no arquivo de paginação na ordem em que as colunas são definidas na tabela. Se a linha contém mais dados do que o arquivo de paginação permite (assumindo que não estamos usando nada que vá para um LOB IMAGE
ou VARCHAR(MAX)
algo assim), o restante é colocado no arquivo de estouro. Se esses dados de estouro forem necessários, haverá esforço extra e tempo gasto fazendo a pesquisa para esse arquivo de estouro. Isso pode resultar em impactos perceptíveis no desempenho em ambientes de alta linha (10 ou 100 de milhões de linhas +). Portanto, gostaríamos de priorizar a ordem das colunas em quantas vezes achamos que a coluna será acessada, não necessariamente se é NULL
ou não.
Essa compreensão/análise parece correta?
Estou postando isso aqui como uma resposta para que eu tenha mais espaço para postar recursos e links, além de explicar um pouco.
Para responder à pergunta específica sobre colunas NULLABLE vs NON-NULLABLE e sua cardinalidade relativa, Kimberly Tripp tem um artigo aqui: https://www.sqlskills.com/blogs/kimberly/column-order-doesnt-matter-generally-but- depende/
Infelizmente, não consigo encontrar a referência que suporta minha afirmação sobre ter colunas de largura variável no final da lista de ordem de coluna, mas o raciocínio era que atualizar uma coluna de largura variável no final de uma linha seria menos provável de causar fragmentação (e desligar -page spill) do que um no meio da ordem das colunas.
Mas, como eu disse anteriormente, é difícil acertar e, a menos que você saiba exatamente seus padrões de acesso a dados, provavelmente errará. Existem muitas outras frutas fáceis de ajustar, preocupando-se com a ordem das colunas. Alternar para comprimentos de coluna estática de tamanho adequado seria uma maneira mais fácil de obter melhores estimativas de memória e evitar a fragmentação.
Índices com fatores de preenchimento adequados, atualizações de estatísticas, procedimentos armazenados para acesso a dados (para que você possa controlar com mais rigor os planos de execução) e muito mais. Se você estiver na edição corporativa, terá mais opções, a compactação de tabelas permitirá que você coloque mais dados na memória e isso é muito mais fácil (e mais amplamente aplicável), o particionamento permitirá que você faça coisas muito legais no lado do gerenciamento (embora use acelerar suas leituras é um desafio (a eliminação de partição é outra coisa difícil de acertar)).
Observe que, quando digo difícil de acertar, geralmente quero dizer que é difícil fazer com que o SQL os use da melhor maneira, portanto, obter ROI pelo tempo gasto na otimização geralmente é muito melhor gasto em outros lugares.
Para responder à última seção da pergunta na seção EDITAR. Sim, pré-carregar a coluna com chaves primárias, chaves estrangeiras e outras colunas de junção provavelmente ajudaria. Mas se você tiver índices nesses, não importa, pois o índice será usado para determinar quais linhas recuperar e, em seguida, uma pesquisa de chave será executada. Eu só não acho que gastar tempo com arquitetura valha o impacto. Você provavelmente terá um índice nessas colunas em qualquer caso.
Caso 1: Não nulo Primeiro
Caso 2: Coluna Nula Primeiro
Clustered index
eNon Clustered Index
são criados intencionalmente para verificarPage Count
,fragmentation
, Contagem de registros em cada página etc. de cada tipo de índice.Descobri que
Fragment_Count
,Page_Count
,record_count
são pouco mais no Caso 2.Portanto , espera-se que o Caso 1 tenha um desempenho MELHOR .
Como eu disse, não tenho permissão para executar
DBCC Page
,DBCC Show_Statistics
etc.Você pode fazer um experimento semelhante e verificar você mesmo e postar sua experiência aqui. Você pega seu exemplo de tabela real e importante.