Azure SQL 搬遷後效能優化實戰:查詢統計、top SQL 分析與索引調整全攻略

🌏 Read the English version


在雲端環境中進行資料庫搬遷或升級(例如從 SQL Server 搬遷至 Azure SQL Database),常會遇到查詢效能下降的情況。本篇將分享我在 Azure SQL 搬遷後的實務優化流程,包括:

  • 一鍵更新統計與索引
  • 查詢前 3 天的 Top SQL
  • 產出最需要調整的索引清單
  • 自動調整設定與注意事項

🧠 為何搬遷後需要重新優化?

  • 查詢計劃重新編譯,可能不同於原環境
  • 統計資料未即時更新
  • Azure I/O 快取與資源排程邏輯不同
  • 原有索引可能未被使用或失效

🔄 Step 1:一鍵更新統計與索引

避免效能問題的第一步是更新統計資料與重建索引:

-- 更新所有統計
EXEC sp_updatestats;

-- 重建所有索引(建議開啟 ONLINE 模式)
EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD WITH (ONLINE = ON)';

📊 Step 2:查詢前 3 天的 Top SQL 分析

✅ 啟用 Query Store(若尚未開啟)

ALTER DATABASE [YourDatabaseName]
SET QUERY_STORE = ON;

✅ 查詢 CPU 時間最高的前 10 筆 SQL(單位:秒)

SELECT TOP 10
    qt.query_sql_text AS SQL語句,
    qs.query_id AS QueryID,
    SUM(rs.count_executions) AS 總執行次數,
    ROUND(AVG(rs.avg_duration) / 1000.0, 3) AS 平均耗時_秒,
    ROUND(AVG(rs.avg_cpu_time) / 1000.0, 3) AS 平均CPU時間_秒
FROM
    sys.query_store_query_text qt
JOIN
    sys.query_store_query qs ON qt.query_text_id = qs.query_text_id
JOIN
    sys.query_store_plan p ON qs.query_id = p.query_id
JOIN
    sys.query_store_runtime_stats rs ON p.plan_id = rs.plan_id
GROUP BY
    qt.query_sql_text, qs.query_id
ORDER BY
    平均CPU時間_秒 DESC;

🧠 Step 3:觀察使用情況,產出索引調整清單

以下查詢可列出所有索引的使用次數與最後一次查詢時間:

SELECT
    OBJECT_NAME(s.object_id) AS TableName,
    i.name AS IndexName,
    s.index_id,
    s.user_seeks,
    s.user_scans,
    s.user_lookups,
    s.user_updates,
    s.last_user_seek,
    s.last_user_scan
FROM sys.dm_db_index_usage_stats s
JOIN sys.indexes i
    ON s.object_id = i.object_id AND s.index_id = i.index_id
WHERE s.database_id = DB_ID()
ORDER BY s.user_seeks + s.user_scans DESC;

指標解讀:

  • user_seeks:使用索引進行查詢的次數
  • user_scans:執行全表掃描的次數
  • user_lookups:使用 Bookmark Lookup 的次數(越高越差)
  • user_updates:維護索引的成本

🛠 Step 4:針對查詢建立適當索引

查詢範例:

SELECT [u].[Time], [u].[UserId], [u].[ProductId]
FROM [UserTakeProductRecords] AS [u]
WHERE ([u].[Time] >= @__todayStartTime_0) AND ([u].[ParentId] = 0)

推薦索引:

CREATE NONCLUSTERED INDEX IX_UserTakeProductRecords_ParentId_Time
ON dbo.UserTakeProductRecords (ParentId, Time)
INCLUDE (UserId, ProductId);

說明:

先使用等值條件 ParentId 再接範圍條件 Time,再以 INCLUDE 避免 Bookmark Lookup。


🤖 Step 5:啟用 Azure SQL 自動調整建議

  • 強制執行計劃(FORCE PLAN):建議開啟 ✅
  • 建立索引(CREATE INDEX):如能控管命名與欄位順序,建議手動處理 ⚠️
  • 捨棄索引(DROP INDEX):建議由工程師審核後執行 ⚠️

Azure SQL 建立/捨棄索引時不會停機,但可能會有短暫鎖定。


📌 結語:Azure SQL 效能調校建議流程

  1. 搬遷後先執行統計與索引重建
  2. 啟用 Query Store 並觀察 Top SQL
  3. 評估冷熱索引使用情況
  4. 為關鍵查詢建立新索引(含 INCLUDE)
  5. 設定自動調整但保留人工審核空間

相關文章

Leave a Comment