Rozwiązywanie problemów i wydajności przy użyciu pakietu SqlPackage

W niektórych scenariuszach operacje SqlPackage trwają dłużej niż oczekiwano lub kończą się niepowodzeniem. W tym artykule opisano niektóre często sugerowane taktyki rozwiązywania problemów lub poprawy wydajności tych operacji. Zaleca się zapoznanie się z konkretnymi stronami dokumentacji dla każdej akcji, aby zrozumieć dostępne parametry i właściwości, jednak ten artykuł służy jako punkt wyjścia do poznania operacji SqlPackage.

Ogólna strategia

Ogólnie rzecz biorąc, lepszą wydajność można uzyskać z wersji .NET SqlPackage zamiast wersji .NET Framework zainstalowanej za pomocą DacFramework.msi.

Jeśli nie możesz zainstalować narzędzia SqlPackage dotnet, które pozwala wykonywać polecenia SqlPackage z wiersza poleceń w dowolnym katalogu:

  1. Pobierz zip dla pakietu SqlPackage na platformie .NET 8 dla systemu operacyjnego (Windows, macOS lub Linux).
  2. Rozpakuj archiwum zgodnie z instrukcjami na stronie pobierania.
  3. Otwórz wiersz polecenia i zmień katalog (cd) na folder SqlPackage.

Korzystaj z najnowszej dostępnej wersji SqlPackage, ponieważ regularnie pojawiają się poprawki wydajności i poprawki błędów.

Zastąp pakiet SqlPackage usługą Import/Export

Jeśli podjęto próbę zaimportowania lub wyeksportowania bazy danych przy użyciu usługi Import/Export, możesz użyć pakietu SqlPackage do wykonania tej samej operacji z większą kontrolą nad opcjonalnymi parametrami i właściwościami. Wpis w blogu Optymalizacja importów BACPAC — SqlPackage Done Right! zawiera instrukcje dotyczące używania pakietu SqlPackage zamiast usługi Import/Export na potrzeby importowania .bacpac .

W przypadku importowania przykładowe polecenie to:

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

W przypadku eksportu przykładowe polecenie to:

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

Używaj uwierzytelniania wieloskładnikowego jako alternatywy dla nazwy użytkownika i hasła, aby uwierzytelnić się za pomocą uwierzytelniania Microsoft Entra. Zastąp parametry nazwy użytkownika i hasła /ua:true i /tid:"contoso.onmicrosoft.com".

Diagnostics

Diagnozowanie błędów i nieoczekiwanego zachowania w pakiecie SqlPackage jest obsługiwane przez dzienniki diagnostyczne i pakiet diagnostyczny. Dzienniki diagnostyczne są niezbędne do rozwiązywania problemów i zapisywane do pliku za pomocą parametru /DiagnosticsFile:<filename>.

Kontroluj poziom szczegółowości w wyjściu diagnostycznym za pomocą parametru /DiagnosticsLevel . Użyj wartości Information i Verbose do uzyskania więcej szczegółów.

Loguj dane śledzenia związane z wydajnością, ustawiając zmienną środowiskową DACFX_PERF_TRACE=true przed uruchomieniem SqlPackage. Dane śledzenia zwiększają ilość danych w logach, więc uwzględniaj je tylko podczas diagnozowania problemów z wydajnością. Aby ustawić tę zmienną środowiskową w programie PowerShell, użyj następującego polecenia:

Set-Item -Path Env:DACFX_PERF_TRACE -Value true

W SqlPackage 162.5 i nowszych możesz wygenerować pakiet diagnostyczny pomagający w rozwiązywaniu problemów. Pakiet diagnostyczny zawiera wersję sqlPackage, wykonane polecenie, informacje o źródłowych i docelowych modelach baz danych oraz dane wyjściowe polecenia. Aby wygenerować pakiet diagnostyczny, użyj parametru /DiagnosticsPackageFile:<filename>.

Typowe problemy

Błędy przekroczenia limitu czasu

W przypadku problemów z limitem czasu używaj następujących właściwości do dostrojenia połączenia między SqlPackage a instancją SQL:

  • /p:CommandTimeout=: Określa limit czasu polecenia w sekundach po uruchomieniu zapytania. Ustawienie domyślne: 60
  • /p:DatabaseLockTimeout=: określa limit czasu blokady bazy danych w sekundach. Użyj -1, aby czekać na czas nieokreślony. Ustawienie domyślne: 60
  • /p:LongRunningCommandTimeout=: określa limit czasu długotrwałego polecenia w sekundach. Domyślna wartość 0, czeka w nieskończoność.

Użycie zasobów klienta

W przypadku poleceń export i extract program SqlPackage przekazuje dane tabel do katalogu tymczasowego w celu ich zbuforowania przed zapisaniem ich do pliku BACPAC lub DACPAC. To zapotrzebowanie na przechowywanie może być duże i jest względne do pełnego rozmiaru danych do eksportu. Określ alternatywny katalog tymczasowy z właściwością /p:TempDirectoryForTableData=<path>.

SqlPackage kompiluje model schematu w pamięci. W przypadku dużych schematów baz danych wymagania dotyczące pamięci na komputerze klienckim uruchamiającym SqlPackage mogą być znaczne.

Niskie zużycie zasobów serwera

Domyślnie pakiet SqlPackage ustawia maksymalną równoległość serwera na 8. Jeśli zauważysz niskie zużycie zasobów serwera, zwiększenie wartości parametru MaxParallelism może poprawić wydajność.

Token dostępu

Użycie parametru /AccessToken: or /at: umożliwia uwierzytelnianie oparte na tokenach dla SqlPackage, ale przekazanie tokena do polecenia może być trudne. Jeśli parsujesz obiekt tokena dostępu w PowerShell, albo jawnie przekazuj wartość ciągu znaków, albo opakuj odwołanie do właściwości token w $(). Przykład:

$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

Jeśli program SqlPackage nie może nawiązać połączenia, serwer może nie mieć włączonego szyfrowania lub skonfigurowany certyfikat może nie zostać wystawiony z zaufanego urzędu certyfikacji (takiego jak certyfikat z podpisem własnym). Możesz zmienić polecenie SqlPackage, aby nawiązać połączenie bez szyfrowania lub zaufać certyfikatowi serwera. Najlepszym rozwiązaniem jest upewnienie się, że można ustanowić zaufane zaszyfrowane połączenie z serwerem.

  • Łączenie bez szyfrowania: /SourceEncryptConnection:False lub /TargetEncryptConnection:False
  • Certyfikat serwera zaufania: /SourceTrustServerCertificate:True lub /TargetTrustServerCertificate:True

Możesz zobaczyć jeden lub więcej z następujących komunikatów ostrzegawczych podczas łączenia z instancją SQL, wskazujących, że parametry wiersza poleceń mogą wymagać zmian, aby połączyć się z serwerem:

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.

Więcej informacji o zmianach zabezpieczeń połączenia w programie SqlPackage jest dostępnych w temacie Ulepszenia zabezpieczeń połączeń w programie SqlPackage 161.

Błąd podczas importowania 2714 dla ograniczenia

Podczas wykonywania akcji importu możesz otrzymać błąd 2714, jeśli obiekt już istnieje:

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

Oto przyczyny i rozwiązania dotyczące tego błędu:

  1. Sprawdź, czy importowane miejsce docelowe jest pustą bazą danych.
  2. Jeśli twoja baza danych ma ograniczenia wykorzystujące DEFAULT atrybut (gdzie SQL Server przypisuje ograniczeniu losową nazwę) oraz wyraźnie nazwane ograniczenie, ograniczenie o tej samej nazwie może zostać utworzone dwukrotnie. Użyj wszystkich jawnie nazwanych ograniczeń (nie używaj DEFAULT), lub używaj wszystkich nazw zdefiniowanych przez system (użyj DEFAULT).
  3. Ręcznie edytuj plik model.xml i zmień nazwę ograniczenia o nazwie powodującej błąd na unikalną nazwę. Ta opcja powinna być podejmowana tylko w przypadku, gdy jest zalecana przez asystę techniczną Microsoft i niesie ryzyko .bacpac uszkodzenia.

Wyjątek przepełnienia stosu

Duże skrypty T-SQL z wieloma zagnieżdżonymi instrukcjami mogą powodować sporadyczne lub utrzymujące się wyjątki przepełnienia stosu. Gdy ten warunek wystąpi, komunikat o błędzie zawiera tekst Stack overflow oraz ślad stosu:

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)

Parametr dla SqlPackage jest dostępny we wszystkich poleceniach, /ThreadMaxStackSize:, który określa maksymalny rozmiar stosu wątku obsługującego proces SqlPackage. Wartość domyślna jest określana przez wersję platformy .NET z uruchomionym pakietem SqlPackage. Ustawienie dużej wartości może wpłynąć na ogólną wydajność SqlPackage. Jednak zwiększenie tej wartości może rozwiązać wyjątek przepełnienia stosu spowodowany zagnieżdżonymi instrukcjami. Zrefaktoryzuj kod T-SQL, aby wszędzie, gdzie to możliwe, unikać wyjątków przepełnienia stosu. Jeśli nie możesz refaktoryzować, użyj parametru /ThreadMaxStackSize: jako obejścia.

Gdy używasz parametru /ThreadMaxStackSize:, jeśli zauważysz wpływ na wydajność, ustaw wartość dla powtarzanych operacji na możliwie najniższą, która pozwala uniknąć wyjątku przepełnienia stosu. Wartość parametru wynosi w megabajtach (MB). Na przykład można testować wartości takie jak 10 i 100.

Porady dotyczące akcji importowania

Dla importów zawierających duże tabele lub tabele z wieloma indeksami, używanie /p:RebuildIndexesOfflineForDataPhase=True lub /p:DisableIndexesForDataPhase=False może poprawić wydajność. Te właściwości modyfikują operację ponownego kompilowania indeksu, aby wystąpiła odpowiednio w trybie offline lub nie. Możesz użyć tych właściwości i innych do dostrojenia operacji importu SqlPackage .

Indeksy są wyłączane po imporcie

Aby efektywnie ładować dane, import wyłącza indeksy nieklastrowane przed fazą danych i buduje je ponownie (domyślne /p:DisableIndexesForDataPhase=True zachowanie). Jeśli import zostanie przerwany lub zawiodł po załadowaniu danych, ale przed zakończeniem odbudowy, jeden lub więcej indeksów nieklastrowanych może pozostać wyłączonych. Wyłączony indeks pozostaje w metadanych, ale optymalizator zapytań go ignoruje, co może powodować powolne zapytania po imporcie, który poza tym pozornie kończy się powodzeniem.

Aby znaleźć wyłączone indeksy, sprawdź kolumnę is_disabled w widoku katalogu 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;

Aby ponownie włączyć wyłączony indeks, odbuduj go za pomocą ALTER INDEX. Użyj ALTER INDEX ALL ... REBUILD, aby włączyć wszystkie wyłączone indeksy w tabeli:

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

Więcej informacji można znaleźć w artykule Włącz indeksy i ograniczenia.

Porady dotyczące akcji eksportowania

Aby eksport był transakcyjnie spójny, upewnij się, że podczas eksportu nie ma aktywności zapisu lub że eksportujesz z transakcyjnie spójnej kopii bazy danych. Jeśli podczas importu otrzymasz błędy dotyczące ograniczeń klucza obcego, eksport może nie być spójny transakcyjnie z powodu wstawionych lub zaktualizowanych rekordów podczas procesu eksportu.

Wydajność podczas eksportowania

Częstą przyczyną pogorszenia wydajności podczas eksportu są nierozwiązane odwołania do obiektów. Ten problem powoduje, że SqlPackage wielokrotnie próbuje rozwiązać ten obiekt. Na przykład zdefiniowany jest widok, który odnosi się do tabeli, ale tabela ta nie istnieje już w bazie danych. Jeśli nierozwiązane odwołania pojawią się w dzienniku eksportu, rozważ poprawienie schematu bazy danych w celu zwiększenia wydajności eksportu.

Podczas procesu eksportowania dane tabeli są kompresowane w pliku bacpac. Ustawienie /p:CompressionOption na Fast, SuperFast, lub NotCompressed może poprawić szybkość procesu eksportu, jednocześnie kompresując plik bacpac na wyjściu mniej.

Aby uzyskać schemat bazy danych i dane podczas pomijania weryfikacji schematu, wykonaj Export z opcją /p:VerifyExtraction=False. Może zostać wygenerowany nieprawidłowy eksport, którego nie można zaimportować.

Miejsce na dysku podczas eksportowania

W sytuacjach, gdy miejsce na dysku systemu operacyjnego jest ograniczone i kończy się podczas eksportu, użyj /p:TempDirectoryForTableData do buforowania danych do eksportu na alternatywnym dysku. Miejsce wymagane dla tej akcji może być duże i jest powiązane z pełnym rozmiarem bazy danych. Możesz dostosować operację SqlPackage Export , ustawiając tę i inne właściwości.

Azure SQL Database

Poniższe porady dotyczą uruchamiania importowania lub eksportowania w kontekście Azure SQL Database z maszyny wirtualnej Azure.

  • Aby uzyskać najlepszą wydajność, użyj bazy danych klasy Business Critical lub Premium.
  • Użyj magazynu SSD na maszynie wirtualnej.
  • Upewnij się, że jest wystarczająco dużo miejsca, aby rozpakować plik .bacpac.
  • Wykonaj pakiet SqlPackage z maszyny wirtualnej w tym samym regionie co baza danych.
  • Włącz przyspieszoną sieć na maszynie wirtualnej.

Więcej informacji o wykorzystaniu skryptu PowerShell do zbierania szczegółów operacji importu znajdziesz w Lesson Learned #211: Monitoring SQLPackage Import Process.

Więcej zasobów

Blog pomocy technicznej usługi Azure Database zawiera wiele artykułów dotyczących rozwiązywania problemów i dostrajania wydajności dla usługi Azure SQL Database, w tym kilka artykułów na temat pakietu SqlPackage.

Oto niektóre z najbardziej odpowiednich artykułów: