Solucionar problemas e desempenho com SqlPackage

Em alguns cenários, as operações do SqlPackage levam mais tempo do que o esperado ou não são concluídas. Este artigo descreve algumas táticas frequentemente sugeridas para solucionar ou melhorar o desempenho dessas operações. Embora seja recomendado ler a página de documentação específica de cada ação para entender os parâmetros e as propriedades disponíveis, este artigo serve como um ponto de partida para investigar as operações do SqlPackage.

Estratégia geral

Como diretriz geral, é possível obter melhor desempenho por meio da versão do .NET de SqlPackage em vez da versão do .NET Framework instalada via DacFramework.msi.

Se você não conseguir instalar a ferramenta dotnet do SqlPaquet, que permite executar comandos do SqlPackage a partir do prompt de comando em qualquer diretório:

  1. Baixe o zip do SqlPackage no .NET 8 para seu sistema operacional (Windows, macOS ou Linux).
  2. Descompacte o arquivo conforme orientado na página de download.
  3. Abra um prompt de comando e altere o diretório (cd) para a pasta do SqlPackage.

Use a versão mais recente disponível do SqlPackage, pois melhorias de desempenho e correções de bugs são lançadas regularmente.

Substituir o SqlPackage pelo Serviço de Importação/Exportação

Se você tentou usar o Serviço de Importação/Exportação para importar ou exportar seu banco de dados, é possível usar o SqlPackage para executar a mesma operação com mais controle sobre os parâmetros e as propriedades opcionais. A postagem no blog Otimizando importações BACPAC – SqlPackage feito corretamente! percorre as etapas para usar o SqlPackage em vez do Serviço de Importação/Exportação para uma importação de .bacpac.

Para importar, um exemplo de comando é:

./SqlPackage /Action:Import /sf:<source-bacpac-file-path> /tsn:<full-target-server-name> /tdn:<a new or empty database> /tu:<target-server-username> /tp:<target-server-password> /df:<log-file>

Para exportar, um exemplo de comando é:

./SqlPackage /Action:Export /tf:<target-bacpac-file-path> /ssn:<full-source-server-name> /sdn:<source-database-name> /su:<source-server-username> /sp:<source-server-password> /df:<log-file>

Use autenticação multifator como alternativa a nome de usuário e senha para se autenticar com a autenticação do Microsoft Entra. Substitua os parâmetros de nome de usuário e senha para /ua:true e /tid:"contoso.onmicrosoft.com".

Diagnostics

O diagnóstico de erros e comportamento inesperado no SqlPackage é suportado por logs de diagnóstico e um pacote de diagnóstico. Os logs de diagnóstico são essenciais para a solução de problemas e são capturados em um arquivo com o parâmetro /DiagnosticsFile:<filename>.

Controle o nível de detalhe na saída de diagnóstico através do /DiagnosticsLevel parâmetro. Use os Information valores e Verbose para obter mais detalhes.

Registre dados de rastreamento relacionados ao desempenho definindo a DACFX_PERF_TRACE=true variável de ambiente antes de executar o SqlPackage. Os dados de rastreamento aumentam a saída logaritária, então inclua-os apenas ao diagnosticar desafios de desempenho. Para definir essa variável de ambiente no PowerShell, use o seguinte comando:

Set-Item -Path Env:DACFX_PERF_TRACE -Value true

No SqlPackage 162.5 e versões posteriores, você pode gerar um pacote de diagnóstico para ajudar na solução de problemas. O pacote de diagnóstico contém a versão do SqlPackage, o comando executado, informações sobre os modelos de banco de dados de origem e de destino e a saída do comando. Para gerar um pacote de diagnóstico, use o parâmetro /DiagnosticsPackageFile:<filename>.

Problemas comuns

Erros do tempo limite

Para questões de timeout, use as seguintes propriedades para ajustar a conexão entre o SqlPackage e a instância SQL:

  • /p:CommandTimeout=: Especifica o tempo limite do comando em segundos quando uma consulta é executada. Padrão: 60
  • /p:DatabaseLockTimeout=: especifica o tempo limite de bloqueio do banco de dados em segundos. Use -1 para esperar indefinidamente. Padrão: 60
  • /p:LongRunningCommandTimeout=: especifica o tempo limite do comando de longa execução em segundos. O valor padrão, 0, espera indefinidamente.

Consumo de recursos do cliente

Para os comandos de exportação e extração, o SqlPackage passa os dados da tabela para um diretório temporário para buffer antes de gravá-los no arquivo BACPAC ou DACPAC. Esse requisito de armazenamento pode ser grande e é relativo ao tamanho total dos dados a serem exportados. Especifique um diretório temporário alternativo com a propriedade /p:TempDirectoryForTableData=<path>.

SqlPackage compila o modelo de esquema na memória. Para esquemas de banco de dados grandes, o requisito de memória na máquina cliente que executa o SqlPackage pode ser significativo.

Baixo consumo de recursos do servidor

Por padrão, o SqlPackage define o paralelismo máximo do servidor como 8. Se você perceber baixo consumo de recursos do servidor, aumentar o valor do MaxParallelism parâmetro pode melhorar o desempenho.

Token de acesso

Usar o parâmetro /AccessToken: ou /at: permite a autenticação baseada em token para o SqlPackage, mas passar o token para o comando pode ser complicado. Se você estiver analisando um objeto de token de acesso no PowerShell, passe explicitamente o valor da string ou enrole a referência na propriedade do token em $(). Por exemplo:

$Account = Connect-AzAccount -ServicePrincipal -Tenant $Tenant -Credential $Credential
$AccessToken_Object = (Get-AzAccessToken -Account $Account -Resource "https://database.windows.net/")
$AccessToken = $AccessToken_Object.Token

SqlPackage /at:$AccessToken
# OR
SqlPackage /at:$($AccessToken_Object.Token)

Connection

Se o SqlPackage apresentar falha ao se conectar, o servidor poderá não ter a criptografia habilitada ou o certificado configurado poderá não ser emitido por uma autoridade de certificação confiável (como um certificado autoassinado). Você pode alterar o comando SqlPackage para se conectar sem criptografia ou confiar no certificado do servidor. A melhor prática é garantir que uma conexão criptografada confiável com o servidor possa ser estabelecida.

  • Conecte-se sem criptografia: /SourceEncryptConnection:False ou /TargetEncryptConnection:False
  • Confiar em certificado do servidor: /SourceTrustServerCertificate:True ou /TargetTrustServerCertificate:True

Você pode ver uma ou mais das seguintes mensagens de aviso ao se conectar a uma instância SQL, indicando que parâmetros de linha de comando podem exigir alterações para se conectar ao servidor:

The settings for connection encryption or server certificate trust may lead to connection failure if the server is not properly configured.
The connection string provided contains encryption settings which may lead to connection failure if the server is not properly configured.

Mais informações sobre as alterações de segurança de conexão no SqlPackage estão disponíveis em Aprimoramentos de segurança de conexão no SqlPackage 161.

Erro de ação de importação 2714 para restrição

Quando você realiza uma ação de importação, pode receber o erro 2714 se um objeto já existir:

*** Error importing database:Could not import package.
Error SQL72014: Core Microsoft SqlClient Data Provider: Msg 2714, Level 16, State 5, Line 1 There is already an object named 'DF_Department_ModifiedDate_0FF0B724' in the database.
Error SQL72045: Script execution error. The executed script:
ALTER TABLE [HumanResources].[Department]
    ADD CONSTRAINT [DF_Department_ModifiedDate_] DEFAULT ('') FOR [ModifiedDate];

Estas são as causas e soluções para contornar esse erro:

  1. Verifique se o destino para o qual você está importando é um banco de dados vazio.
  2. Se seu banco de dados tiver restrições que usam o DEFAULT atributo (onde o SQL Server atribui um nome aleatório à restrição) e uma restrição explicitamente nomeada, uma restrição com o mesmo nome pode ser criada duas vezes. Use todas as restrições explicitamente nomeadas (não use DEFAULT), ou use todos os nomes definidos pelo sistema (use DEFAULT).
  3. Edite manualmente o model.xml arquivo e renomeie a restrição com o nome que causa o erro para um nome único. Essa opção deve ser realizada apenas sob orientação do suporte da Microsoft, pois apresenta risco de corrupção do .bacpac.

Exceção do excedente de pilha

Scripts T-SQL extensos com muitas instruções aninhadas podem causar exceções intermitentes ou persistentes de estouro de pilha. Quando essa condição ocorre, a mensagem de erro inclui o texto Stack overflow e um rastreio de pilha:

Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor.Visit(Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression)
Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor.ExplicitVisit(Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression)
Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression.Accept(Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor)
Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression.AcceptChildren(Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor)
Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression.Accept(Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor)
Microsoft.SqlServer.TransactSql.ScriptDom.BinaryQueryExpression.AcceptChildren(Microsoft.SqlServer.TransactSql.ScriptDom.TSqlFragmentVisitor)

Um parâmetro para o SqlPackage está disponível em todos os comandos, /ThreadMaxStackSize:, que especifica o tamanho máximo da pilha para a thread que executa o processo SqlPackage. O valor padrão é determinado pela versão do .NET que executa o SqlPackage. Definir um valor alto pode afetar o desempenho geral do SqlPackage. No entanto, aumentar esse valor pode resolver a exceção de estouro de pilha causada por instruções aninhadas. Refatore o código T-SQL para evitar exceções de estouro de pilha sempre que possível. Se não conseguir refatorar, use o /ThreadMaxStackSize: parâmetro como solução alternativa.

Quando você usa o /ThreadMaxStackSize: parâmetro, ajuste as operações repetidas para o menor valor que resolva a exceção de overflow da pilha caso note um impacto no desempenho. O valor do parâmetro está em megabytes (MB). Por exemplo, você pode testar valores como 10 e 100.

Dicas sobre ação de importação

Para importações que contêm tabelas grandes ou tabelas com muitos índices, usar /p:RebuildIndexesOfflineForDataPhase=True ou /p:DisableIndexesForDataPhase=False pode melhorar o desempenho. Essas propriedades modificam a operação de recompilação de índice para que ela ocorra offline ou não ocorra, respectivamente. Você pode usar essas propriedades e outras para ajustar a operação de importação do SqlPaket .

Índices são desativados após uma importação

Para carregar os dados de forma eficiente, uma importação desativa índices não agrupados antes da fase de dados e os reconstrói depois (o comportamento padrão /p:DisableIndexesForDataPhase=True ). Se a importação for interrompida ou falhar após o carregamento dos dados, mas antes do término da reconstrução, um ou mais índices não agrupados podem permanecer desativados. Um índice desativado permanece nos metadados, mas o otimizador de consultas o ignora, o que pode causar consultas lentas após uma importação que, de outra forma, parece ter sucesso.

Para encontrar índices desativados, verifique a coluna is_disabled na exibição de catálogo sys.indexes:

SELECT OBJECT_SCHEMA_NAME(object_id) AS schema_name,
       OBJECT_NAME(object_id) AS table_name,
       name AS index_name
FROM sys.indexes
WHERE is_disabled = 1;

Para reativar um índice desativado, reconstrua-o com ALTER INDEX. Use ALTER INDEX ALL ... REBUILD para ativar todos os índices desativados em uma tabela:

ALTER INDEX ALL ON <schema>.<table> REBUILD;

Para mais informações, veja Habilitar índices e restrições.

Dicas da ação de exportação

Para que uma exportação seja transacionalmente consistente, certifique-se de que nenhuma atividade de escrita esteja ocorrendo durante a exportação, ou que você esteja exportando a partir de uma cópia transacionalmente consistente do seu banco de dados. Se você receber erros sobre restrições de chave estrangeira durante uma importação, a exportação pode não ser transacionalmente consistente devido a registros inseridos ou atualizados durante o processo de exportação.

Desempenho durante a exportação

Uma causa comum de degradação de desempenho durante a exportação são referências de objetos não resolvidas. Esse problema faz com que o SqlPackage tente resolver o objeto várias vezes. Por exemplo, uma visualização é definida que faz referência a uma tabela, mas a tabela não existe mais no banco de dados. Se aparecerem referências não resolvidas no log de exportação, considere corrigir o esquema do banco de dados para aprimorar o desempenho de exportação.

Durante um processo de exportação, os dados da tabela são compactados no arquivo bacpac. Definir /p:CompressionOption para Fast, SuperFast, ou NotCompressed pode melhorar a velocidade do processo de exportação enquanto comprime menos o arquivo bacpac de saída.

Para obter o esquema de banco de dados e os dados ao ignorar a validação de esquema, execute uma Exportação com a propriedade /p:VerifyExtraction=False. Pode ser produzida uma exportação inválida que não pode ser importada.

Espaço em disco durante a exportação

Em cenários onde o espaço em disco do sistema operacional é limitado e acaba durante a exportação, use-o /p:TempDirectoryForTableData para armazenar os dados para exportação em um disco alternativo. O espaço necessário para essa ação pode ser grande e é relativo ao tamanho total do banco de dados. Você pode ajustar a operação de exportação do SqlPackage definindo essa e outras propriedades.

Banco de Dados SQL do Azure

As dicas a seguir são específicas para executar a importação ou exportação para o Banco de Dados SQL do Azure de uma VM (máquina virtual) do Azure:

  • Use o banco de dados de nível Comercialmente Crítico ou Premium para obter o melhor desempenho.
  • Use o armazenamento SSD na VM.
  • Verifique se há espaço suficiente para descompactar o bacpac.
  • Execute o SqlPackage em uma VM na mesma região que o banco de dados.
  • Habilite a rede acelerada na VM.

Para mais informações sobre o uso de um script PowerShell para coletar detalhes sobre uma operação de importação, veja Lição Aprendida #211: Monitorando o Processo de Importação do SQLPackage.

Mais recursos

O Blog de Suporte do Banco de Dados do Azure contém vários artigos de solução de problemas e ajuste de desempenho para o Banco de Dados SQL do Azure, incluindo vários artigos sobre SqlPackage.

Alguns dos artigos mais relevantes são: