Résoudre les problèmes et le niveau de performance avec SqlPackage

Dans certains scénarios, les opérations SqlPackage prennent plus de temps que prévu ou échouent. Cet article décrit certaines tactiques fréquemment suggérées pour résoudre ou améliorer le niveau de performance de ces opérations. Tout en étudiant la page de documentation spécifique pour chaque action afin de comprendre les paramètres et propriétés disponibles, cet article sert de point de départ pour enquêter sur des opérations SqlPackage.

Stratégie globale

En règle générale, de meilleures performances peuvent être obtenues via la version .NET de SqlPackage au lieu de la version .NET Framework installée via le DacFramework.msi.

Si vous ne pouvez pas installer l’outil dotnet SqlPackage, qui vous permet d’exécuter des commandes SqlPackage depuis l’invite de commande dans n’importe quel répertoire :

  1. Téléchargez le fichier zip pour SqlPackage sur .NET 8 pour votre système d’exploitation (Windows, macOS ou Linux).
  2. Décompressez l’archive comme indiqué sur la page de téléchargement.
  3. Ouvrez une invite de commandes et changez de répertoire vers le dossier SqlPackage à l'aide de cd.

Utilisez la dernière version disponible de SqlPackage, car des améliorations de performance et des corrections de bugs sont régulièrement publiées.

Remplacer SqlPackage pour le service Import/Export

Si vous avez tenté d’utiliser le service Import/Export pour importer ou exporter votre base de données, vous pouvez utiliser SqlPackage pour effectuer la même opération avec plus de contrôle sur les paramètres et les propriétés facultatifs. Le billet de blog Optimisation des importations BACPAC - SqlPackage Done Right ! décrit les étapes à suivre pour utiliser SqlPackage au lieu du service Import/Export pour une .bacpac importation.

Voici un exemple de commande pour l’importation :

./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>

Voici un exemple de commande pour l’exportation :

./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>

Utilisez l’authentification multifacteur comme alternative au nom d’utilisateur et au mot de passe, pour s’authentifier avec l’authentification Microsoft Entra. Remplacez les paramètres de nom d’utilisateur et de mot de passe pour /ua:true et /tid:"contoso.onmicrosoft.com".

Diagnostics

Le diagnostic des erreurs et du comportement inattendu dans SqlPackage est pris en charge par les journaux de diagnostic et un package de diagnostic. Les journaux de diagnostic sont essentiels à la résolution des problèmes et sont capturés dans un fichier avec le paramètre /DiagnosticsFile:<filename>.

Contrôlez le niveau de détail dans la sortie de diagnostic via le /DiagnosticsLevel paramètre. Utilisez les Information valeurs et Verbose pour obtenir plus de détails.

Enregistrez les données de traces liées à la performance en définissant la variable d’environnement avant d’exécuter DACFX_PERF_TRACE=true SqlPackage. Les données de trace augmentent la sortie logarithmique, donc ne les incluez que lors du diagnostic des problèmes de performance. Pour définir cette variable d’environnement dans PowerShell, utilisez la commande suivante :

Set-Item -Path Env:DACFX_PERF_TRACE -Value true

Dans SqlPackage 162.5 et les versions ultérieures, vous pouvez générer un package de diagnostic pour aider au dépannage. Le package de diagnostic contient la version sqlPackage, la commande exécutée, des informations sur les modèles de base de données source et cible et la sortie de la commande. Pour générer un package de diagnostic, utilisez le paramètre /DiagnosticsPackageFile:<filename>.

Problèmes courants

Erreurs de délai d’expiration

Pour les problèmes de timeout, utilisez les propriétés suivantes pour ajuster la connexion entre SqlPackage et l’instance SQL :

  • /p:CommandTimeout=: Spécifie le délai d’expiration de la commande en secondes lors de l’exécution d’une requête. Valeur par défaut : 60
  • /p:DatabaseLockTimeout= : spécifie le délai d'attente pour le verrou de la base de données en secondes. Utilisez -1 pour attendre indéfiniment. Valeur par défaut : 60
  • /p:LongRunningCommandTimeout= : spécifie le délai d'expiration de la commande de longue durée en secondes. La valeur par défaut, 0, attend indéfiniment.

Consommation de ressources client

Pour les commandes d’exportation et d’extraction, SqlPackage transfère les données des tables vers un répertoire temporaire afin de les mettre en mémoire tampon avant de les écrire dans le fichier BACPAC ou DACPAC. Cette exigence de stockage peut être importante et est relative à la taille totale des données à exporter. Spécifiez un autre répertoire temporaire avec la propriété /p:TempDirectoryForTableData=<path>.

SqlPackage compile le modèle de schéma en mémoire. Pour les grands schémas de bases de données, la demande en mémoire sur la machine cliente exécutant SqlPackage peut être importante.

Faible consommation des ressources du serveur

Par défaut, SqlPackage définit le parallélisme de serveur maximal sur 8. Si vous remarquez une faible consommation de ressources serveur, augmenter la valeur du MaxParallelism paramètre peut améliorer les performances.

Access token (Jeton d’accès)

L’utilisation du paramètre /AccessToken: ou /at: permet l’authentification par jeton pour SqlPackage, mais transmettre le jeton à la commande peut s’avérer délicat. Si vous analysez un objet token d’accès dans PowerShell, passez explicitement la valeur de la chaîne ou encapsulez la référence à la propriété du token dans $(). Par exemple:

$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

En cas d’échec de la connexion de SqlPackage, le chiffrement du serveur n’est peut-être pas activé ou le certificat configuré peut ne pas être émis à partir d’une autorité de certification approuvée (par exemple un certificat auto-signé). Vous pouvez modifier la commande SqlPackage pour vous connecter sans chiffrement ou pour faire confiance au certificat du serveur. La meilleure pratique consiste à s’assurer qu’une connexion chiffrée de confiance au serveur peut être établie.

  • Se connecter sans chiffrement : /SourceEncryptConnection:False ou /TargetEncryptConnection:False
  • Faire confiance au certificat de serveur : /SourceTrustServerCertificate:True ou /TargetTrustServerCertificate:True

Vous pourriez voir un ou plusieurs des messages d’avertissement suivants lors de la connexion à une instance SQL, indiquant que les paramètres de la ligne de commande peuvent nécessiter des modifications pour se connecter au serveur :

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.

Pour en savoir plus sur les modifications apportées à la sécurité des connexions dans SqlPackage, reportez-vous à Améliorations de la sécurité des connexions dans SqlPackage 161.

Erreur d’action d’importation 2714 pour contrainte

Lorsque vous effectuez une action d’importation, vous pouvez recevoir l’erreur 2714 si un objet existe déjà :

*** 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];

Les causes et solutions pour contourner cette erreur sont les suivantes :

  1. Vérifiez que la destination dans laquelle vous importez est une base de données vide.
  2. Si votre base de données possède des contraintes qui utilisent l’attribut DEFAULT (où SQL Server attribue un nom aléatoire à la contrainte) et une contrainte nommée explicitement, une contrainte portant le même nom peut être créée deux fois. Utilisez toutes les contraintes nommées explicitement (ne pas utiliser DEFAULT), ou utilisez tous les noms définis par le système (utilisez DEFAULT).
  3. Modifiez manuellement le model.xml fichier et renommez la contrainte avec le nom qui cause l’erreur en un nom unique. Cette option ne doit être entreprise que sur instruction du support Microsoft et présente un risque de corruption du .bacpac.

Exception de Stack Overflow

De gros scripts T-SQL avec de nombreuses instructions imbriquées peuvent provoquer des exceptions intermittentes ou persistantes de débordement de pile. Lorsque cette condition se produit, le message d’erreur inclut le texte Stack overflow et une trace de pile :

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)

Un paramètre pour SqlPackage est disponible sur toutes les commandes, /ThreadMaxStackSize:qui spécifie la taille de pile maximale pour le thread exécutant le processus SqlPackage. La valeur par défaut est déterminée par la version .NET exécutant SqlPackage. Définir une grande valeur peut affecter la performance globale de SqlPackage. Cependant, augmenter cette valeur pourrait résoudre l’exception de débordement de pile causée par des instructions imbriquées. Remanier le code T-SQL pour éviter, autant que possible, les exceptions de débordement de pile. Si vous ne pouvez pas refactoriser, utilisez ce /ThreadMaxStackSize: paramètre comme solution de contournement.

Lorsque vous utilisez ce /ThreadMaxStackSize: paramètre, ajustez les opérations répétées à la valeur la plus basse qui résout l’exception de débordement de pile si vous constatez un impact sur la performance. La valeur du paramètre est en mégaoctets (Mo). Par exemple, vous pouvez tester des valeurs comme 10 et 100.

Conseils sur les actions d’importation

Pour les importations contenant de grandes tables ou des tables avec de nombreux indices, utiliser /p:RebuildIndexesOfflineForDataPhase=True ou /p:DisableIndexesForDataPhase=False peut améliorer les performances. Ces propriétés modifient l’opération de reconstruction d’index pour qu’elle se produise hors connexion ou qu’elle ne se produise pas, respectivement. Vous pouvez utiliser ces propriétés et d’autres pour ajuster l’opération d’importation de SqlPaket .

Les index sont désactivés après une importation

Pour charger les données efficacement, une importation désactive les index non clusterisés avant la phase de données et les reconstruit ensuite (comportement par défaut /p:DisableIndexesForDataPhase=True ). Si l’importation est interrompue ou échoue après le chargement des données mais avant la fin de la reconstruction, un ou plusieurs index non clusterisés peuvent rester désactivés. Un index désactivé reste dans les métadonnées, mais l’optimiseur de requêtes l’ignore, ce qui peut ralentir les requêtes après une importation qui semble par ailleurs réussir.

Pour trouver les index désactivés, vérifiez la is_disabled colonne dans la vue catalogue 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;

Pour réactiver un index désactivé, reconstruisez-le avec ALTER INDEX. À utiliser ALTER INDEX ALL ... REBUILD pour activer tous les index désactivés sur un tableau :

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

Pour plus d’informations, voir Activer les index et contraintes.

Conseils sur les actions d’exportation

Pour qu’une exportation soit transactionnellement cohérente, assurez-vous soit qu’aucune activité d’écriture n’a lieu pendant l’exportation, soit que vous exportez depuis une copie transactionnellement cohérente de votre base de données. Si vous recevez des erreurs concernant les contraintes de clé étrangère lors d’une importation, l’exportation peut ne pas être transactionnellement cohérente en raison d’enregistrements insérés ou mis à jour pendant le processus d’exportation.

Performance lors de l’exportation

Une cause fréquente de dégradation des performances lors de l’exportation est la présence de références d’objets non résolues. Ce problème pousse SqlPackage à tenter plusieurs fois de résoudre l’objet. Par exemple, une vue est définie qui fait référence à une table, mais la table n’existe plus dans la base de données. Si des références non résolues apparaissent dans le journal d’exportation, envisagez de corriger le schéma de la base de données pour améliorer les performances d’exportation.

Pendant un processus d’exportation, les données de table sont compressées dans le fichier bacpac. Régler /p:CompressionOption à Fast, SuperFast, ou NotCompressed pourrait améliorer la vitesse du processus d’exportation tout en comprimant moins le fichier bacpac de sortie.

Pour obtenir le schéma et les données de la base de données tout en passant la validation du schéma, effectuez une exportation avec /p:VerifyExtraction=False. Une exportation non valide peut être produite qui ne peut pas être importée.

Espace disque pendant l’exportation

Dans les situations où l’espace disque du système d’exploitation est limité et s’épuise lors de l’exportation, utilisez /p:TempDirectoryForTableData pour tampon les données pour l’exportation sur un disque alternatif. L’espace requis pour cette action peut être important et dépend de la taille totale de la base de données. Vous pouvez régler l’opération d’exportation de SqlPackage en configurant cette propriété et d’autres.

Azure SQL Database

Les conseils suivants sont spécifiques à l’exécution de l’importation ou de l’exportation sur Azure SQL Database à partir d’une machine virtuelle Azure :

  • Utilisez la base de données critique pour l'entreprise ou de niveau Premium pour des performances optimales.
  • Utilisez le stockage SSD sur l’ordinateur virtuel.
  • Assurez-vous qu’il y a suffisamment de place pour décompresser le bacpac.
  • Exécutez SqlPackage à partir d’une machine virtuelle dans la même région que la base de données.
  • Activez les performances réseau accélérées pour la machine virtuelle.

Pour plus d’informations sur l’utilisation d’un script PowerShell pour collecter des détails sur une opération d’importation, voir Leçon apprise #211 : Surveillance du processus d’importation SQLPackage.

Plus de ressources

Le blog du support de la base de données Azure SQL contient de nombreux articles sur le dépannage et le réglage des performances pour la base de données Azure SQL, y compris plusieurs articles sur SqlPackage.

Quelques-uns des articles les plus pertinents :