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

DB2 for z/OS 程式設計師減少 SQL 往返之道 (上):消除無用 COUNT(*)

     編輯:DB2 教學

核心哲理

「沒有比不執行的 SQL 性能更好的 SQL 了。」—— Prem Mehra

本系列針對:完全無用 SQL (應刪除)、過度執行 SQL (應減少)、應替換 SQL。目標:減少甚至消除對 DB2 的連接,善用 DB2 8/9 新特性解決老問題。

問題一:UPDATE 前的 SELECT COUNT(*)

SELECT COUNT(*) INTO :hvcount FROM EMP WHERE STATUS = 'T';
UPDATE EMP SET STATUS = 'P' WHERE STATUS = 'T';

兩大錯誤

  1. 計數不準:除非 ISOLATION RR 或獨佔維護存取,COUNT 讀取合格行與實際 UPDATE 行數可能不同 (中間可能發生 DELETE/INSERT/UPDATE)。
  2. 根本多餘:DB2 更新行時會計數,結果在 SQLCA 的 SQLERRD(3) 回傳。測試程式時直接檢查此欄位即可。

DB2 計數例外

  • 分段表空間/通用表空間 (DB2 9 新增) 無 WHERE 子句刪除全表:DB2 不逐行尋址故不計數。
  • 三種例外會計數:啟用 DATA CAPTURE、調用 VALIDPROC、使用行級安全性。但批量 DELETE 常用於工作/臨時表,極少觸發例外。
  • DB2 9 TRUNCATE TABLE:重新初始化 (重設 HURBA 或刪除重建 VSAM 數據集),同樣不計行數。

問題二:單行用 Singleton SELECT、多行用 CURSOR 的錯誤模式

SELECT COUNT(*) INTO :hvcount FROM T WHERE ...;
IF :hvcount = 1 THEN
  SELECT ... INTO ... FROM T WHERE ...;  -- Singleton
ELSE
  DECLARE CURSOR ...; OPEN ...; FETCH ...;  -- Cursor
END IF;

錯誤分析

  • 讀取計數行、再讀取處理行 = 兩次讀取。即使頁面在緩衝池,DB2 是動態維護機器,消除連接可顯著降低 CPU/GETPAGE 開銷。
  • 「單行機率 98%」不代表要先 COUNT。

正確策略

  1. 先執行 Singleton SELECT。
  2. 收到 -811 (multiple rows) 錯誤 → 再開 Cursor。
  3. 若多行為主 → 直接開 Cursor,忽略 Singleton 回饋。
  4. 原則:優先採用最普遍情況的方式,失敗再回退。

問題三:分頁顯示為了「Page 1 of n」而 COUNT(*)

SELECT COUNT(*) INTO :hvcount FROM T WHERE ...;
-- 計算總頁數 = :hvcount / 10 (每頁 10 行)

分層優化策略

典型情況策略效益
通常 1 頁或少量頁開 Cursor,FETCH 時計數。讀到第 11 行遇 EOF 即知總頁數省去 COUNT 所有 GETPAGE/READ I/O
通常 11-30 行 (2-3 頁)讀取並計數。第 31 行計數達 100 → 存入 COMMAREA,首頁顯示「Page 1 of 3」避免多數情況下兩次讀取
3 頁以上將用戶實際看到內容存 COMMAREA,延遲到最晚才執行 COUNT大多數情況避免 COUNT,程式邏輯健全

結語

日常用 DB2 者請檢視自身代碼。下期將提供更多無用 SQL 範例與優秀替換方案。敬請期待第 2 部分。

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