在部分案例中,SqlPackage 作業花費的時間超乎預期或無法完成。 此文章描述一些常見的建議策略,以針對這些作業進行疑難排解或改善效能。 儘管建議您閱讀每個動作適用的特定文件頁面來了解可用的參數與屬性,但可將此文章當作調查 SqlPackage 作業的起點。
整體策略
一般指導方針是透過 .NET 版本的 SqlPackage 取得更好的效能,而不是透過 DacFramework.msi 安裝的 .NET Framework 版本。
如果你無法安裝 SqlPackage dotnet 工具,該工具能讓你在任何目錄的命令提示字元執行 SqlPackage 指令:
- 在適用於您作業系統 (Windows、macOS 或 Linux) 的 .NET 8 上,下載 SqlPackage 的 zip 檔案。
- 按照下載頁面指示解壓壓縮檔案。
- 開啟命令提示字元,並將目錄變更為 (
cd) SqlPackage 資料夾。
請使用最新版本的 SqlPackage,因為效能改進與錯誤修正會定期發布。
以 SqlPackage 取代匯入/匯出服務
如果曾嘗試使用匯入/匯出服務來匯入或匯出資料庫,您可以使用 SqlPackage 來執行相同作業,並且能夠更充分控制選擇性參數與屬性。 部落格文章《最佳化 BACPAC 匯入 - 正確使用 SqlPackage!》逐步講解了如何使用 SqlPackage 來取代匯入/匯出服務進行.bacpac匯入。
針對匯入,範例命令為:
./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>
針對匯出,範例命令為:
./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>
使用多重驗證作為使用者名稱和密碼的替代方案,並使用 Microsoft Entra 認證。 以使用者名稱與密碼參數取代 /ua:true 與 /tid:"contoso.onmicrosoft.com"。
Diagnostics
診斷記錄和診斷套件支持診斷 SqlPackage 中的錯誤和非預期行為。 診斷記錄對於疑難解答至關重要,而且會擷取至具有 /DiagnosticsFile:<filename> 參數的檔案。
透過參數 /DiagnosticsLevel 控制診斷輸出的細節程度。 使用 Information 和 Verbose 的值以取得更多詳細資訊。
在執行 SqlPackage 前,先透過設定 DACFX_PERF_TRACE=true 環境變數來記錄與效能相關的追蹤資料。 追蹤資料會增加日誌輸出,因此僅在診斷效能問題時納入。 若要在 PowerShell 中設定此環境變數,請使用下列命令:
Set-Item -Path Env:DACFX_PERF_TRACE -Value true
在 SqlPackage 162.5 及以後版本中,你可以產生診斷套件來協助故障排除。 診斷套件包含 SqlPackage 版本、執行命令、來源和目標資料庫模型的相關信息,以及命令的輸出。 若要產生診斷套件,請使用 /DiagnosticsPackageFile:<filename> 參數。
常見問題
逾時錯誤
對於逾時問題,請使用以下屬性來調整 SqlPackage 與 SQL 實例之間的連線:
-
/p:CommandTimeout=: 指定查詢執行時的指令逾時時間(秒數)。 預設值:60 -
/p:DatabaseLockTimeout=:指定資料庫的鎖定逾時秒數。 使用-1表示永遠等候。 預設值:60 -
/p:LongRunningCommandTimeout=:指定長時間執行的命令逾時 (以秒為單位)。 預設值0,會無限期等待。
用戶端資源耗用量
對於匯出與擷取指令,SqlPackage 會將資料傳入暫存目錄以緩衝,然後再寫入 BACPAC 或 DACPAC 檔案。 這個儲存需求可能很大,且相對於要匯出的資料總大小而言。 使用 /p:TempDirectoryForTableData=<path> 屬性來指定替代的暫存目錄。
SqlPackage 在記憶體中編譯結構模型。 對於大型資料庫結構,執行 SqlPackage 的用戶端機器的記憶體需求可能相當可觀。
伺服器資源耗用量降低
根據預設,SqlPackage 會將伺服器平行處理原則上限設定為 8。 如果你發現伺服器資源消耗很低,提高參數值 MaxParallelism 可以提升效能。
存取憑證
使用 /AccessToken: or /at: 參數可啟用基於 SqlPackage 的憑證驗證,但將 token 傳給指令時可能會很棘手。 如果你在 PowerShell 解析存取權杖物件,要麼明確傳遞字串值,要麼將權杖屬性的參考包裝成 $()。 例如:
$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
如果 SqlPackage 無法連線,則伺服器可能未啟用加密,或設定的憑證可能不是由信任的憑證授權單位所發出 (例如自我簽署憑證)。 您可以將 SqlPackage 命令變更為在沒有加密的情況下連線,或信任伺服器憑證。 最佳做法 是確保能夠建立一個受信任的加密連線到伺服器。
- 在沒有加密的情況下連線:
/SourceEncryptConnection:False或/TargetEncryptConnection:False - 信任伺服器憑證:
/SourceTrustServerCertificate:True或/TargetTrustServerCertificate:True
當你連接到 SQL 實例時,可能會看到以下一個或多個警告訊息,表示命令列參數可能需要更改才能連接到伺服器:
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.
如需有關 SqlPackage 中連線安全性變更的詳細資訊,請參閱 SqlPackage 161 中的連線安全性改進。
匯入動作約束條件錯誤 2714
當你執行匯入動作時,如果物件已經存在,可能會收到錯誤 2714:
*** 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];
以下是解決此錯誤的原因和解決方案:
- 確認您要匯入的目的地是否為空資料庫。
- 如果你的資料庫有使用屬性
DEFAULT(SQL Server 會隨機指派約束名稱)和明確命名的限制,則同名的限制可能會被建立兩次。 使用所有明確命名的限制(不使用DEFAULT),或使用所有系統定義的名稱(使用DEFAULT)。 - 手動編輯
model.xml檔案,並將造成錯誤的名稱重新命名限制,讓它變成唯一名稱。 僅當 Microsoft 支援服務指示且有.bacpac損毀風險時,才應採用此選項。
堆疊溢位例外狀況
大型 T-SQL 腳本若包含許多巢狀語句,可能會導致間歇性或持續性的堆疊溢位異常。 當發生此條件時,錯誤訊息會包含文字 Stack overflow 及堆疊追蹤:
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)
SqlPackage 的參數 /ThreadMaxStackSize: 可在所有命令上使用,這會指定執行 SqlPackage 程序之執行緒的堆疊大小上限。 預設值由執行 SqlPackage 的 .NET 版本所決定。 設定較大值會影響 SqlPackage 的整體效能。 然而,增加此值可能解決巢狀語句所造成的堆疊溢位異常。 盡可能重構 T-SQL 程式碼以避免堆疊溢位例外。 如果你無法重構,可以用這個 /ThreadMaxStackSize: 參數作為變通方法。
使用 /ThreadMaxStackSize: 參數時,將重複操作調整到能解決堆疊溢位異常的最低值,以防效能影響。 參數值以兆位元組(MB)為單位。 例如,你可以測試像 10 和 100這樣的值。
匯入動作提示
對於包含大型資料表或多索引資料表的匯入,使用 /p:RebuildIndexesOfflineForDataPhase=True 或 /p:DisableIndexesForDataPhase=False 能提升效能。 這些屬性會分別將索引重建作業修改為離線發生或不發生。 你可以利用這些屬性和其他屬性來調整 SqlPackage 匯入 操作。
匯入後索引會被停用
為了有效率地載入資料,匯入會在資料階段前停用非叢集索引,並在之後重建它們(預設 /p:DisableIndexesForDataPhase=True 行為)。 若匯入在資料載入後、重建完成前被中斷或失敗,一個或多個非叢集索引可能會被停用。 停用的索引會保留在中繼資料中,但查詢最佳化工具會忽略它,這可能導致在看似成功的匯入作業之後,查詢速度變慢。
要查找已停用的索引,請在 sys.indexes 目錄檢視中查看欄位is_disabled:
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;
若要重新啟用已停用的索引,請使用 ALTER INDEX 重建該索引。 使用 ALTER INDEX ALL ... REBUILD 來啟用資料表上所有已停用的索引:
ALTER INDEX ALL ON <schema>.<table> REBUILD;
更多資訊請參見 啟用索引與約束。
匯出動作提示
為了讓匯出在交易上保持一致,請確保匯出過程中沒有寫入活動,或是你從 交易相容 的資料庫副本匯出。 如果您在匯入期間遇到與外鍵限制相關的錯誤,則匯出可能不具備交易一致性,因為在匯出過程中有紀錄被插入或更新。
出口期間的性能
匯出時效能下降的常見原因是物件參照未解決。 此問題導致 SqlPackage 多次嘗試解析該物件。 例如,定義了一個檢視,參考一個資料表,但該資料表已不存在於資料庫中。 如果匯出記錄中出現無法解析的參考,請考慮更正資料庫的結構描述來提升匯出效能。
在匯出流程期間,會在 bacpac 檔案中壓縮資料表資料。 設定 /p:CompressionOption 為 Fast、 SuperFast或 NotCompressed 可能會提升匯出速度,同時減少輸出 bacpac 檔案的壓縮。
若要在略過結構描述驗證的情況下取得資料庫結構描述與資料,請使用具有
匯出時的磁碟空間
當作業系統磁碟空間有限且匯出時用盡時,請將 /p:TempDirectoryForTableData 資料緩衝至替代磁碟。 此動作所需的空間可能很大 (相對於資料庫的完整大小)。 你可以透過設定這個和其他屬性來調整 SqlPackage 匯出 操作。
Azure SQL Database
下列提示是針對從 Azure 虛擬機器 (VM) 執行匯入或匯出 Azure SQL Database 的特定提示:
- 使用業務關鍵或進階層資料庫來獲得最佳效能。
- 在 VM 上使用 SSD 儲存體。
- 請確定有足夠的空間來解壓縮 bacpac。
- 從與資料庫相同區域中的 VM 執行 SqlPackage。
- 在 VM 中啟用加速網路。
欲了解更多使用 PowerShell 腳本收集匯入操作細節的資訊,請參閱 Lesson Learned #211:監控 SQLPackage 匯入流程。
更多資源
Azure 資料庫支援部落格包含許多文章,涉及 Azure SQL 資料庫的疑難排解和效能微調,包括有關 SqlPackage 的數篇文章。
其中一些最相關的文章包括:
- 優化 BACPAC 匯入 - 正確使用 SqlPackage!
- 經驗教訓 #535:由於使用者不相容導致 BACPAC 在 Azure SQL 資料庫匯入失敗
- 經驗教訓 #523:使用 PowerShell 測量匯入時間並解析 SqlPackage 日誌
- 如何在匯出/還原 Azure SQL 資料庫時跳過外部資料來源參考
- 使用 SqlPackage/ADF 將 Azure SQL DB 移轉至 SQL MI
- 經驗傳承 #446:使用 PowerShell 簡化 SQLPackage 記錄偵錯
- 如何搭配受控識別使用 Sqlpackage
- 經驗傳承 #298:使用 sqlpackage 匯出資料庫需要很長時間
- 經驗傳承 #281:匯出因系統記憶體不足的例外狀況而失敗
- 經驗傳承 #281:針對因業務邏輯造成匯入 bacpac 的 CHECK 條件約束問題進行疑難排解
- 經驗教訓 #272:匯入 Bacpac 檔案出現「執行逾時已過期」錯誤訊息
- 經驗傳承 #213:如果已設定整合式安全性,則無法設定 AccessToken 屬性
- 經驗傳承 #211:監視 SQLPackage 匯入處理程序
- 教訓 #51:管理的執行個體 - 透過 Sqlpackage.exe 匯入不允許自動擴展
- 經驗傳承 #32:如何將多個資料庫從 SQL Server 匯出至 Bacpac
- 逐步解說:如何搭配存取權杖使用 SQLPackage
- 使用 SQLPackage 將 Azure SQL DB 移轉到內部部署的 SQL Server 或 Azure VM 時發生的定序衝突