Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Melhore o desempenho de consulta do SQL Server em tabelas grandes


Resposta Simples:NÃO. Você não pode ajudar em consultas ad hoc em uma tabela de 238 colunas com um fator de preenchimento de 50% no índice clusterizado.

Resposta detalhada:

Como afirmei em outras respostas sobre este tópico, o design do índice é arte e ciência e há tantos fatores a serem considerados que existem poucas, se houver, regras rígidas e rápidas. Você precisa considerar:o volume de operações DML vs SELECTs, subsistema de disco, outros índices/triggers na tabela, distribuição de dados dentro da tabela, são consultas usando condições SARGable WHERE, e várias outras coisas que nem lembro direito agora.

Posso dizer que nenhuma ajuda pode ser dada para perguntas sobre este tópico sem uma compreensão da própria Tabela, seus índices, gatilhos, etc. Agora que você postou a definição da tabela (ainda aguardando os Índices, mas a definição da Tabela sozinha aponta para 99% da questão) posso oferecer algumas sugestões.

Primeiro, se a definição da tabela for precisa (238 colunas, 50% de fator de preenchimento), você poderá ignorar o restante das respostas / conselhos aqui;-). Desculpe ser menos do que político aqui, mas falando sério, é uma perseguição sem saber os detalhes. E agora que vemos a definição da tabela, fica um pouco mais claro por que uma consulta simples levaria tanto tempo, mesmo quando as consultas de teste (Atualização #1) foram executadas tão rapidamente.

O principal problema aqui (e em muitas situações de baixo desempenho) é a modelagem de dados ruim. 238 colunas não é proibido, assim como ter 999 índices não é proibido, mas geralmente também não é muito sábio.

Recomendações:
  1. Primeiro, esta mesa precisa ser remodelada. Se esta for uma tabela de data warehouse, talvez, mas se não, esses campos realmente precisam ser divididos em várias tabelas que podem ter o mesmo PK. Você teria uma tabela de registro mestre e as tabelas filhas são apenas informações dependentes com base em atributos comumente associados e o PK dessas tabelas é o mesmo que o PK da tabela mestre e, portanto, também FK para a tabela mestre. Haverá uma relação de 1 para 1 entre as tabelas mestre e todas as tabelas filhas.
  2. O uso de ANSI_PADDING OFF é perturbador, para não mencionar inconsistente dentro da tabela devido às várias adições de colunas ao longo do tempo. Não tenho certeza se você pode corrigir isso agora, mas idealmente você sempre teria ANSI_PADDING ON , ou pelo menos ter a mesma configuração em todos os ALTER TABLE declarações.
  3. Considere a criação de 2 grupos de arquivos adicionais:tabelas e índices. É melhor não colocar suas coisas em PRIMARY pois é onde o SQL SERVER armazena todos os seus dados e metadados sobre seus objetos. Você cria sua tabela e índice clusterizado (já que são os dados da tabela) em [Tables] e todos os índices não agrupados em [Indexes]
  4. Aumente o fator de preenchimento de 50%. Esse número baixo provavelmente é o motivo pelo qual seu espaço de índice é maior que seu espaço de dados. Fazer uma reconstrução de índice recriará as páginas de dados com um máximo de 4k (do tamanho total de página de 8k) usado para seus dados para que sua tabela seja espalhada por uma área ampla.
  5. Se a maioria ou todas as consultas tiverem "ER101_ORG_CODE" em WHERE condição, considere movê-la para a coluna principal do índice clusterizado. Supondo que seja usado com mais frequência que "ER101_ORD_NBR". Se "ER101_ORD_NBR" for usado com mais frequência, mantenha-o. Parece que, assumindo que os nomes dos campos significam "OrganizationCode" e "OrderNumber", que "OrgCode" é um agrupamento melhor que pode ter vários "OrderNumbers" dentro dele.
  6. Ponto menor, mas se "ER101_ORG_CODE" tiver sempre 2 caracteres, use CHAR(2) em vez de VARCHAR(2) pois ele salvará um byte no cabeçalho da linha que rastreia tamanhos de largura variável e soma milhões de linhas.
  7. Como outros aqui mencionaram, usando SELECT * prejudicará o desempenho. Não apenas por exigir que o SQL Server retorne todas as colunas e, portanto, seja mais provável que faça uma verificação de índice clusterizado, independentemente de seus outros índices, mas também leva tempo do SQL Server para ir para a definição da tabela e traduzir * em todos os nomes de coluna. Deve ser ligeiramente mais rápido para especificar todos os 238 nomes de coluna no SELECT list embora isso não ajude o problema de digitalização. Mas você realmente precisa de todas as 238 colunas ao mesmo tempo?

Boa sorte!

ATUALIZAÇÃO
Para completar a pergunta "como melhorar o desempenho em uma tabela grande para consultas ad-hoc", deve-se notar que, embora não ajude neste caso específico, SE alguém estiver usando o SQL Server 2012 (ou mais recente quando chegar a hora) e SE a tabela não estiver sendo atualizada, usar Columnstore Indexes é uma opção. Para obter mais detalhes sobre esse novo recurso, veja aqui:http://msdn.microsoft.com/en-us/library/gg492088.aspx (acredito que eles foram feitos para serem atualizados a partir do SQL Server 2014).

ATUALIZAÇÃO 2
Considerações adicionais são:
  • Ative a compactação no índice clusterizado. Essa opção ficou disponível no SQL Server 2008, mas como um recurso somente do Enterprise Edition. No entanto, a partir do SQL Server 2016 SP1 , a Compressão de Dados foi disponibilizada em todas as edições! Consulte a página MSDN para compactação de dados para obter detalhes sobre compactação de linha e página.
  • Se você não puder usar a compactação de dados, ou se ela não fornecer muito benefício para uma tabela específica, SE você tiver uma coluna do tipo de comprimento fixo (INT , BIGINT , TINYINT , SMALLINT , CHAR , NCHAR , BINÁRIO , DATETIME , SMALLDATETIME , DINHEIRO , etc) e bem mais de 50% das linhas são NULL , considere ativar o SPARSE opção que ficou disponível no SQL Server 2008. Consulte a página do MSDN para usar colunas esparsas para obter detalhes.