對於上億筆資料的表進行排序或 Join,極易導致 CPU、記憶體、磁碟 I/O 全面飆升,甚至癱瘓整台伺服器。本文記錄一次真實案例的分析與解決方案,供大數據量操作參考。
問題現場
- 涉及表約 2 億筆記錄,含
GROUP BY 操作。
- 單純
SELECT COUNT(*) FROM table1 就耗時 1 分鐘,記憶體暴增 5 GB,磁碟子系統負載極高,CPU 瞬間飆升。
- 大量磁碟 I/O 導致同主機其他服務(如網站資料庫)回應變慢。
根因分析
- 單一大查詢佔用過多資源:未分區、未分批,一次性掃描 2 億列。
- 磁碟規劃不當:網站資料庫與統計臨時庫共用同一磁碟陣列(C/D 盤實為同一組),I/O 互搶。
- 資料檔案自動增長設定過小:每次增長 1 MB,空間不足時頻繁擴展,產生大量碎片與 I/O。
- 大量 DELETE 產生海量交易記錄:記錄檔曾重建縮小,後續操作又頻繁增長,加劇磁碟壓力。
解決方案
針對原因一:拆分大表操作(分治法)
將大查詢按業務維度(如省份)或時間維度拆解為 30+ 個小查詢,各自處理後再 UNION ALL 合併結果。這能將單次資源佔用降低數十倍,避免系統失去回應。
針對原因二:磁碟隔離(架構層面)
建議將統計/分析資料庫獨立部署至專屬磁碟陣列,與線上交易資料庫(OLTP)物理隔離,避免 I/O 爭用。若無法立即調整硬體,可排程在離峰時段跑批次作業。
針對原因三:調整檔案增長策略 + 空間監控
- 將資料檔案自動增長改為 固定大小(如 512 MB 或 1 GB),而非百分比或極小值。
- 定期清理無用臨時資料,保留足夠可用空間。
- 建立 空間監控告警:當資料檔案觸發自動增長時,立即發送郵件通知 DBA 介入擴容或清理。
針對原因四:截斷記錄檔並控制增長
執行 BACKUP LOG ... WITH TRUNCATE_ONLY(簡單復原模式下)或切換至簡單模式後 DBCC SHRINKFILE,將記錄檔維持在低水位。長期應設定合理的自動增長值(如 100 MB),避免頻繁擴展。
最佳實踐小結
- 億級操作必須分批、分區、分時段,切忌單一大交易。
- 資料與記錄檔預先配置足夠空間,設定固定增量。
- OLTP 與 OLAP物理隔離儲存,避免 I/O 干擾。
- 建立自動化監控與告警,將人工介入前置化。