Beheben von Problemen und Leistungsproblemen mit SqlPackage

In einigen Szenarien dauern SqlPackage-Vorgänge länger als erwartet oder können nicht abgeschlossen werden. In diesem Artikel werden einige häufig vorgeschlagene Methoden zur Problembehandlung oder zur Verbesserung der Leistung dieser Vorgänge beschrieben. Beim Lesen der Dokumentationsseite für die jeweilige Aktion, um die empfohlenen verfügbaren Parameter und Eigenschaften zu verstehen, dient dieser Artikel als Ausgangspunkt für die Untersuchung von SqlPackage-Vorgängen.

Gesamtstrategie

Als Faustregel gilt, dass mit der .NET-Version von SqlPackage eine bessere Leistung erzielt werden kann als mit der über DacFramework.msi installierten .NET Framework-Version.

Wenn Sie das SqlPackage dotnet-Tool nicht installieren können, das es Ihnen ermöglicht, SqlPackage-Befehle aus der Eingabeaufforderung in jedem beliebigen Verzeichnis auszuführen:

  1. Laden Sie die ZIP-Datei für SqlPackage unter .NET 8 für Ihr Betriebssystem (Windows, macOS oder Linux) herunter.
  2. Entpacken Sie das Archiv wie angegeben auf der Download-Seite.
  3. Öffnen Sie eine Eingabeaufforderung und wechseln Sie das Verzeichnis (cd) in den Ordner „SqlPackage“.

Verwenden Sie die aktuellste verfügbare Version von SqlPackage, da regelmäßig Leistungsverbesserungen und Fehlerbehebungen veröffentlicht werden.

Ersetzen des Import/Export-Diensts durch SqlPackage

Wenn Sie versucht haben, den Import/Export-Dienst zum Importieren oder Exportieren Ihrer Datenbank zu verwenden, können Sie SqlPackage nutzen, um denselben Vorgang mit mehr Kontrolle über optionale Parameter und Eigenschaften durchzuführen. Der Blogbeitrag Optimieren von BACPAC Imports - SqlPackage Done Right! führt die Schritte zum Verwenden von SqlPackage anstelle des Import-/Exportdiensts für einen .bacpac Import durch.

Ein Beispielbefehl für „Import“ lautet:

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

Ein Beispielbefehl für „Export“ lautet:

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

Verwenden Sie Multifaktor-Authentifizierung als Alternative zu Benutzernamen und Passwort, um sich mit Microsoft Entra-Authentifizierung zu authentifizieren. Ersetzen Sie /ua:true und /tid:"contoso.onmicrosoft.com" durch die Parameter „username“ (Benutzername) und „password“ (Kennwort).

Diagnostics

Diagnosefehler und unerwartetes Verhalten in SqlPackage werden von Diagnoseprotokollen und einem Diagnosepaket unterstützt. Die Diagnoseprotokolle sind für die Problembehandlung unerlässlich und werden mit dem parameter /DiagnosticsFile:<filename> in einer Datei erfasst.

Steuern Sie den Detailgrad der diagnostischen Ausgabe über den Parameter /DiagnosticsLevel . Verwenden Sie die Werte Information und Verbose, um mehr Details zu erhalten.

Protokollieren Sie leistungsbezogene Trace-Daten, indem Sie die DACFX_PERF_TRACE=true Umgebungsvariable setzen, bevor Sie SqlPackage ausführen. Die Trace-Daten erhöhen die Logausgabe, daher sollten sie nur bei der Diagnose von Leistungsproblemen berücksichtigt werden. Verwenden Sie zum Festlegen dieser Umgebungsvariablen in PowerShell den folgenden Befehl:

Set-Item -Path Env:DACFX_PERF_TRACE -Value true

In SqlPackage 162.5 und später kann man ein Diagnosepaket generieren, das bei der Fehlerbehebung hilft. Das Diagnosepaket enthält die SqlPackage-Version, den ausgeführten Befehl, Informationen zu den Quell- und Zieldatenbankmodellen und die Ausgabe des Befehls. Verwenden Sie den /DiagnosticsPackageFile:<filename>-Parameter, um ein Diagnosepaket zu generieren.

Häufig auftretende Probleme

Timeoutfehler

Bei Timeout-Problemen verwenden Sie die folgenden Eigenschaften, um die Verbindung zwischen SqlPackage und der SQL-Instanz abzustimmen:

  • /p:CommandTimeout=: Gibt das Timeout des Befehls in Sekunden an, wenn eine Abfrage ausgeführt wird. Standard: 60
  • /p:DatabaseLockTimeout=: gibt das Timeout für Datenbanksperren in Sekunden an. Verwenden Sie -1, um unbegrenzt zu warten. Standard: 60
  • /p:LongRunningCommandTimeout=: legt das Timeout für lang laufende Befehle in Sekunden fest. Der Standardwert, 0, wartet unbegrenzt.

Nutzung von Clientressourcen

Für die Export- und Extraktionsbefehle übergibt SqlPackage Tabellendaten an ein temporäres Verzeichnis zum Puffern, bevor es sie in die BACPAC- oder DACPAC-Datei schreibt. Dieser Speicherbedarf kann groß sein und ist relativ zur Gesamtgröße der zu exportierenden Daten. Geben Sie mit der Eigenschaft /p:TempDirectoryForTableData=<path> ein alternatives temporäres Verzeichnis an.

SqlPackage kompiliert das Schemamodell im Speicher. Für große Datenbankschemata kann der Speicherbedarf auf dem Client-Rechner, der SqlPackage ausführt, erheblich sein.

Geringe Nutzung von Serverressourcen

Standardmäßig legt SqlPackage die maximale Serverparallelität auf 8 fest. Wenn Sie einen geringen Serverressourcenverbrauch bemerken, kann eine Erhöhung des MaxParallelism Parameters die Leistung verbessern.

Zugriffstoken

Die Verwendung des Parameters /AccessToken: oder /at: ermöglicht die tokenbasierte Authentifizierung für SqlPackage, aber es kann schwierig sein, das Token an den Befehl zu übergeben. Wenn Sie ein Zugriffstoken-Objekt in PowerShell parsen, geben Sie entweder explizit den String-Wert durch oder wickeln Sie die Referenz auf die Token-Eigenschaft in $(). Beispiel:

$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

Wenn SqlPackage keine Verbindung herstellen kann, ist die Verschlüsselung auf dem Server möglicherweise nicht aktiviert, oder das konfigurierte Zertifikat wird nicht von einer vertrauenswürdigen Zertifizierungsstelle ausgestellt (z. B. ein selbstsigniertes Zertifikat). Sie können den SqlPackage-Befehl ändern, um entweder eine Verbindung ohne Verschlüsselung herzustellen oder dem Serverzertifikat zu vertrauen. Die bewährte Methode besteht darin, sicherzustellen, dass eine vertrauenswürdige verschlüsselte Verbindung mit dem Server hergestellt werden kann.

  • Ohne Verschlüsselung verbinden: /SourceEncryptConnection:False oder /TargetEncryptConnection:False
  • Serverzertifikat vertrauen: /SourceTrustServerCertificate:True oder /TargetTrustServerCertificate:True

Sie könnten beim Verbinden mit einer SQL-Instanz eine oder mehrere der folgenden Warnmeldungen sehen, die anzeigen, dass Kommandozeilenparameter Änderungen erfordern könnten, um sich mit dem Server zu verbinden:

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.

Weitere Informationen zu den Verbindungssicherheitsänderungen in SqlPackage finden Sie unter Verbesserungen der Verbindungssicherheit in SqlPackage 161.

Importaktionsfehler 2714 für Einschränkung

Wenn Sie eine Importaktion ausführen, könnten Sie den Fehler 2714 erhalten, wenn bereits ein Objekt existiert:

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

Dies sind die Ursachen und Lösungen zur Behebung dieses Fehlers:

  1. Stellen Sie sicher, dass das Ziel, in das Sie importieren, eine leere Datenbank ist.
  2. Wenn Ihre Datenbank Einschränkungen enthält, die das Attribut DEFAULT verwenden (wobei SQL Server der Einschränkung einen zufälligen Namen zuweist) und eine explizit benannte Einschränkung, könnte eine Einschränkung mit demselben Namen zweimal erstellt werden. Verwenden Sie entweder alle explizit benannten Einschränkungen (verwenden Sie nicht DEFAULT) oder alle systemdefinierten Namen (verwenden Sie DEFAULT).
  3. Bearbeiten Sie die model.xml Datei manuell und benennen Sie die Constraint mit dem Namen, der den Fehler verursacht, in einen eindeutigen Namen um. Diese Option sollte nur durchgeführt werden, wenn sie von der Microsoft-Unterstützung geleitet wird und ein Risiko von .bacpac-Korruption darstellt.

Stapelüberlauf-Ausnahme

Große T-SQL-Skripte mit vielen verschachtelten Anweisungen können intermittierende oder persistente Stack-Overflow-Ausnahmen verursachen. Wenn diese Bedingung auftritt, enthält die Fehlermeldung den Text Stack overflow und eine Stack-Spur:

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)

Für alle Befehle ist ein Parameter für SqlPackage verfügbar (/ThreadMaxStackSize:), der die maximale Stapelgröße für den Thread angibt, der den SqlPackage-Prozess ausführt. Der Standardwert wird durch die .NET-Version bestimmt, in der SqlPackage ausgeführt wird. Das Setzen eines hohen Wertes kann die Gesamtleistung von SqlPackage beeinflussen. Eine Erhöhung dieses Wertes könnte jedoch die durch verschachtelte Anweisungen verursachte Stack-Overflow-Ausnahme beheben. Refaktorisieren Sie den T-SQL-Code, um wann immer möglich Stack-Overflow-Ausnahmen zu vermeiden. Wenn du nicht refaktorisieren kannst, nutze den Parameter /ThreadMaxStackSize: als Workaround.

Wenn du den Parameter /ThreadMaxStackSize: verwendest, justiere wiederholte Operationen auf den niedrigsten Wert, der die Stack-Overflow-Ausnahme löst, falls du eine Leistungsbeeinträchtigung bemerkst. Der Wert des Parameters beträgt Megabyte (MB). Zum Beispiel können Sie Werte wie 10 und 100testen.

Tipps zu Importaktionen

Für Importe, die große Tabellen oder Tabellen mit vielen Indizes enthalten, kann die Verwendung von /p:RebuildIndexesOfflineForDataPhase=True oder /p:DisableIndexesForDataPhase=False die Leistung verbessern. Diese Eigenschaften ändern den Indexneuerstellungsvorgang so, dass er offline bzw. nicht ausgeführt wird. Sie können diese Eigenschaften und andere Eigenschaften verwenden, um die SqlPackage Import-Operation zu optimieren.

Indizes werden nach einem Import deaktiviert

Um die Daten effizient zu laden, deaktiviert ein Import nicht-geclusterte Indizes vor der Datenphase und baut sie danach wieder auf (das Standardverhalten /p:DisableIndexesForDataPhase=True ). Wenn der Import nach dem Datenladen, aber vor Abschluss des Rebuilds, unterbrochen wird oder fehlschlägt, können ein oder mehrere nicht geclusterte Indizes deaktiviert bleiben. Ein deaktivierter Index bleibt in den Metadaten, aber der Abfrageoptimierer ignoriert ihn, was nach einem Import, der ansonsten erfolgreich zu sein scheint, langsame Abfragen verursachen kann.

Um deaktivierte Indizes zu finden, überprüfen Sie die Spalte is_disabled in der sys.indexes-Katalogansicht :

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;

Um einen deaktivierten Index wieder zu aktivieren, bauen Sie ihn mit ALTER INDEXneu auf. Verwenden Sie ALTER INDEX ALL ... REBUILD, um alle deaktivierten Indizes für eine Tabelle zu aktivieren:

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

Weitere Informationen finden Sie unter Indizes und Constraints aktivieren.

Tipps zu Exportaktionen

Damit ein Export transaktionskonsistent ist, stellen Sie sicher, dass während des Exports keine Schreibaktivität stattfindet oder dass Sie aus einer transaktionskonsistenten Kopie Ihrer Datenbank exportieren. Wenn Sie während eines Imports Fehler aufgrund von Fremdschlüsselbeschränkungen erhalten, ist der Export möglicherweise nicht transaktional konsistent, da während des Exportvorgangs Datensätze eingefügt oder aktualisiert wurden.

Leistung während des Exports

Eine häufige Ursache für Leistungsverschlechterung während des Exports sind ungelöste Objektreferenzen. Dieses Problem führt dazu, dass SqlPackage versucht, das Objekt mehrfach aufzulösen. Zum Beispiel wird eine Ansicht definiert, die auf eine Tabelle referenziert, aber die Tabelle existiert nicht mehr in der Datenbank. Wenn das Exportprotokoll nicht aufgelöste Verweise enthält, sollten Sie erwägen, das Schema der Datenbank zu korrigieren, um die Exportleistung zu verbessern.

Bei einem Exportvorgang werden die Daten der Tabelle in der Bacpac-Datei komprimiert. Das Setzen /p:CompressionOption auf Fast, SuperFast, oder NotCompressed könnte die Exportgeschwindigkeit verbessern, während die Ausgabe-Bacpac-Datei weniger komprimiert wird.

Zum Abrufen des Datenbankschemas und von Daten beim Überspringen der Schemaüberprüfung führen Sie einen Export mit der Eigenschaft /p:VerifyExtraction=False aus. Unter Umständen wird ein ungültiger Export generiert, der nicht importiert werden kann.

Speicherplatz während des Exports

In Szenarien, in denen der Speicherplatz des Betriebssystems begrenzt ist und während des Exports ausgeht, wird verwendet /p:TempDirectoryForTableData , um die Daten für den Export auf einer alternativen Festplatte zu puffern. Der für diese Aktion erforderliche Speicherplatz kann sehr groß ausfallen und steht im Verhältnis zur vollständigen Größe der Datenbank. Du kannst die SqlPackage Export-Operation optimieren, indem du diese und andere Eigenschaften einstellst.

Azure SQL-Datenbank

Die folgenden Tipps beziehen sich auf den Import oder Export in Azure SQL-Datenbank von einer Azure-VM:

  • Verwenden Sie für optimale Leistung eine Datenbank der Ebene „Unternehmenskritisch“ oder „Premium“.
  • Verwenden Sie SSD-Speicher auf der virtuellen Maschine.
  • Stellen Sie sicher, dass genügend Platz zum Entpacken des Bacpac vorhanden ist.
  • Führen Sie SqlPackage auf einer VM aus, die sich in derselben Region wie die Datenbank befindet.
  • Aktivieren Sie den beschleunigten Netzwerkbetrieb für die VM.

Weitere Informationen zur Verwendung eines PowerShell-Skripts, um Details über einen Importvorgang zu erfassen, finden Sie unter Lesson Learned #211: Überwachung des SQLPackage-Importvorgangs.

Weitere Ressourcen

Der Blog zur Unterstützung von Azure-Datenbanken enthält viele Artikel zur Problembehandlung und Leistungsoptimierung für Azure SQL-Datenbank, darunter mehrere Artikel zu SqlPackage.

Zu den relevantesten Artikeln gehören: