首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

以演算法視角優化 SQL Server 批次運算:從游標到集合式思維

     編輯:關於SqlServer

資料庫運算的兩種範式

  • 批次運算 (Set-based):一次讀取大量資料頁、處理後批次寫回,資源消耗低、速度快、鎖定範圍可控。
  • 游標逐列處理 (Row-by-row):逐筆讀取、複雜業務邏輯計算、寫回,佔用大量記憶體/CPU、速度慢、易造成長時間鎖定與阻塞。

原則:能用集合式解決,絕不使用游標。

案例一:學生成績等級分類

表 student_Score(sno, cno, score, level),依分數段寫入等級:90↑=A, 80-89=B, 60-79=C, <60=D。

方法 1:游標(最差)

逐筆讀取、判斷、更新,每筆至少 2 次 I/O,N 筆資料 2N 次存取。

方法 2:多次批次 UPDATE(尚可)

UPDATE student_Score SET level='D';
UPDATE student_Score SET level='C' WHERE score BETWEEN 60 AND 79;
UPDATE student_Score SET level='B' WHERE score BETWEEN 80 AND 89;
UPDATE student_Score SET level='A' WHERE score BETWEEN 90 AND 100;

缺點:高分資料列被重複更新 4 次(D→C→B→A),產生額外 I/O 與記錄檔寫入。

方法 3:查閱表 + 單次 UPDATE(最佳)

建立對照表 level_about(start_score, end_score, level):

INSERT INTO level_about VALUES (0, 59, 'D'), (60, 79, 'C'), (80, 89, 'B'), (90, 100, 'A');

單一陳述式完成:

UPDATE student_Score
SET level = la.level
FROM level_about la
WHERE student_Score.score BETWEEN la.start_score AND la.end_score;

優點:單次掃描、無重複更新、邏輯集中維護、擴充性佳(新增分數段只改對照表)。

案例二:排程自動結算(簡單演算法直套)

需求:每日 00:00 結算,週一/週四額外結算獎金。
建立單列表 misc(days INT) 記錄運行天數,每日排程 UPDATE misc SET days=days+1。
判斷獎金日:IF @days%7=0 OR (@days-3)%7=0(第 0、3、7、10…天)。
此類確定性演算法可直接在 T-SQL 實作,無需複雜轉換。

案例三:複雜獎金扣除與贈品邏輯(需重構演算法)

規則:每 4000 元獎金扣 400 元作「重複消費」,滿 400 元贈 1 件商品,餘額遞延下期。
表結構:
- member(total_award, repeat_num) 累計獎金與已贈次數
- award_day 當期獎金與扣除暫存
- award_repeat 重複消費明細
- award 實發獎金

批次演算法:
1. 當期獎金先累加至 member.total_award。
2. 迴圈條件 F1:total_award >= (repeat_num+1)*4000。
3. 滿足 F1 的會員:寫入 award_repeat、member.repeat_num++,重複檢查 F1 直到無符合者。
4. 最後由 award_day 扣除本期應扣金額得實發數。

結論

資料庫演算法優化關鍵在於:
- 熟悉業務規則與資料特徵。
- 善用集合式思維、查閱表、遞迴 CTE、窗口函數替代游標。
- 將複雜迴圈轉換為「條件篩選 + 批次更新 + 迭代收斂」模式。
隨著業務複雜度提升,演算法與 SQL 的深度融合將成為資料庫開發核心競爭力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved