Melhorar a velocidade da reconstrução do índice no SQL server

9

Estou importando uma grande quantidade de dados para um banco de dados vazio e, antes de começar, desabilitei todos os índices não clusterizados não exclusivos para ver se eu poderia melhorar o desempenho da importação.

Agora, quero reativar os índices e estou pensando se há algo que eu possa fazer para otimizar isso.

Existem> 100 tabelas e quase 2.000 índices a serem reconstruídos. O banco de dados tem 200 GB de tamanho.

A seção principal do script que estou executando é a seguinte:

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

Eu considerei definir ONLINE = OFF para a instrução alter index, mas como os índices começam desativados, eu não tinha certeza de que essa configuração teria algum efeito. Também considerei definir SORT_IN_TEMPDB = ON, mas como os arquivos tempdb estão na mesma unidade que os arquivos .mdf dos bancos de dados, presumi que também não havia nenhum benefício em fazer isso.

Durante a execução do script de reconstrução, notei que tenho muitos tipos de espera CXPACKET. Eu realmente não entendo por que isso seria ou se é um problema que eu deveria estar procurando resolver.

Um último ponto que pode ser relevante: meu servidor inteiro está inativo no momento, além dessa importação de dados no banco de dados. Não há outra atividade do usuário para considerar ou se preocupar; minha única preocupação é importar os dados para o banco de dados no menor tempo possível.

paulH
fonte
3
Quando você diz que sua única preocupação é o tempo de importação, você quer dizer o tempo desde o início da importação até o final da reativação dos índices? Nesse caso, você deve deixar os índices ativados durante a importação. 2.000 índices para dados de 200 GB me parecem muitos índices. Talvez você deva examinar as DMVs de uso do índice para ver se há algumas que podem ser removidas.
Max Vernon
11
Só para esclarecer, você precisa fazer a mesma importação de 200 GB repetidamente, e não apenas uma vez?
22813 Jon Seigel
11
Eu só preciso fazer a importação uma vez, mas como parte de um processo maior com uma janela de tempo limitada, por isso estou testando esse processo para ajustá-lo nessa janela. @MaxVernon Parece que você está certo que deixar os índices ativados é a maneira mais rápida, embora eu esteja surpreso ao ler que normalmente era mais rápido desativar os índices, importar os dados e reativar os índices. Este é um banco de dados de terceiros, portanto, remover índices ou alterá-lo não é realmente possível.
PaulH
3
OK. Sobre as CXPACKETesperas: o índice é reconstruído por si próprio, os índices de varredura (mesmo o índice sendo reconstruído ) e essas varreduras podem usar paralelismo. Você não deve se preocupar com essas esperas - o paralelismo provavelmente está ajudando.
22813 Jon Seigel

Respostas:

10

Atingir o desempenho ideal de importação neste cenário requer três coisas:

  1. Inserções de tabela base com registro mínimo
  2. Construções de índice não clusterizadas com log mínimo
  3. Evitando leituras físicas

Registro Mínimo

A obtenção de inserções minimamente registradas em uma tabela em cluster vazia sem índices não clusterizados requer:

  1. Usando os modelos de recuperação SIMPLEou de BULK_LOGGEDbanco de dados
  2. Especificando um bloqueio de tabela e entrada ordenada (por exemplo, TABLOCKe ORDERdicas)

Nota:

Também é possível obter inserções minimamente registradas em uma tabela em cluster que possui índices não clusterizados, desde que o sinalizador de rastreamento 610 esteja ativado. Se as inserções de índice não clusterizadas são minimamente registradas ou não, depende do plano de consulta selecionado pelo otimizador de consultas.

Se o plano de consulta usar um iterador separado para o índice não clusterizado e o iterador tiver a DMLRequestSortpropriedade definida como true, as inserções de índice não clusterizadas serão minimamente registradas, desde que as outras condições mencionadas anteriormente sejam atendidas.

Criando índices não clusterizados separadamente

As vantagens de fazer isso são:

  1. As inserções de índice em cluster podem ser minimamente registradas sem ativar o TF 610
  2. CREATE INDEX é registrado minimamente se o modelo de recuperação não for FULL

Evitando leituras físicas

Idealmente, os dados a serem importados serão armazenados em uma máquina separada ou, pelo menos, em um armazenamento físico separado daquele usado para hospedar o banco de dados.

O servidor de banco de dados deve ter memória suficiente para armazenar a maior tabela base no cache, com sobras suficientes para as operações de classificação necessárias ao criar índices não clusterizados.

Um bom padrão é carregar rapidamente a tabela base (carregamento de índice clusterizado minimamente registrado) e criar todos os índices não clusterizados para essa tabela enquanto suas páginas de dados ainda estiverem em cache.

A pergunta descreve um processo pelo qual as tabelas base são carregadas primeiro e, em seguida, construídos os índices não clusterizados. A definição do cursor não usa uma ORDER BYcláusula para pelo menos agrupar compilações de índice não clusterizadas na mesma tabela.

O resultado provável é que as páginas de dados para tabelas diferentes sejam lidas repetidamente no cache e descartadas à medida que os índices não clusterizados são criados em uma ordem não determinística.

O custo de leituras físicas repetidas domina completamente os benefícios do registro mínimo obtido com a criação de índices não clusterizados separadamente. Isso explica por que você descobriu que carregar tabelas com índices existentes é mais rápido (porque todos os índices não clusterizados para uma determinada tabela são mantidos antes de passar para a próxima tabela).

Sumário

O processo de importação deve ser reformulado para carregar em massa uma tabela por vez. Isso significa carregar a tabela e criar todos os índices não clusterizados antes de passar para o próximo. A instância do SQL Server deve ter memória suficiente disponível para armazenar a maior tabela e executar a maior classificação de índice não clusterizado ao mesmo tempo.

Você também pode tentar ativar o TF 610 antes de carregar os dados em tabelas com índices não clusterizados já em vigor. Geralmente não é tão rápido quanto o método anterior, mas pode ser rápido o suficiente.

Consulte o seguinte para obter mais informações:

O Guia de Desempenho de Carregamento de Dados

Operações que podem ser registradas minimamente

Paul White 9
fonte