程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> 程序員:使用 DB2 for z/OS 減少會話:第 1 部分:Prem Mehra 說過:“沒有比不執行的 SQL 性能更好的 SQL 了。”

程序員:使用 DB2 for z/OS 減少會話:第 1 部分:Prem Mehra 說過:“沒有比不執行的 SQL 性能更好的 SQL 了。”

編輯:DB2教程

很久以前,某同事 (Prem Mehra) 向我介紹了無用 SQL 的概念,以及他再三引用的真理:“沒有比不執行的 SQL 性能更好的 SQL 了。”在本系列文章中,我們將討論完全沒有用的、應該刪除的 SQL、過度執行的 SQL,以及應該被替換的 SQL。目標是什麼呢?如果可能,減少到 DB2 的連接,並完全刪除一些連接。還有什麼目標呢?了解 IBM DB2 8 和 DB2 9 中針對這些老問題的最新解決方案。因此,了解了我們了目標之後,歡迎閱讀本系列文章的第 1 部分:如何刪除或減少到 DB2 的連接。

COUNT(*):問題 1

在編寫應該時應該嚴格遵守一些基本的性能規則。其中之一是刪除程序中的所有沒有用的 SELECT COUNT。另一個是如果無法安全避免則應該減少執行 COUNT 的數量。下面我們來看一些例子:

程序員:使用 DB2 for z/OS 減少會話:第 1 部分:Prem Mehra 說過:“沒有比不執行的 SQL 性能更好的 SQL 了。”

我在看到這樣的 SQL 時,不免會產生疑問。為何會有一個 COUNT 在 UPDATE 前面?我進行了深入研究。是否檢查了主機變量?如果它是 0,那麼它的操作是什麼呢?如果 COUNT 大於 0 會怎麼樣呢?下一個操作會依賴於 :hvcount 的內容嗎?

COUNT 經常都是不必要的,並且可以完全清除。在本例中,程序員可能希望知道在執行 UPDATE 語句時會有多少個臨時 (T) 員工將被更新為永久 (P) 狀態。

這種方法存在兩處錯誤。首先,除非您使用 ISOLATION RR,或者擁有對表的獨占性維護訪問,否則 COUNT 數量的合格的行讀取與實際更新的行的數量會有不同。可以在 COUNT 和實際 UPDATE 之間執行刪除、插入或更新操作。

但是,另一個更加重要的問題在於 COUNT 是沒有必要的,因為 DB2 會在行更新時計算並在 SQL Communications Area (SQLCA) 的 SQLERRD(3) 中返回計算。您在測試程序時,可以檢查這個 SQLCA 字段是否包含所需的 COUNT 信息。

據我所知,在執行維護時,DB2 會盡可能計入您的行。我知道至少有兩個例外:

在分段表空間中刪除(DELETE)某個表中的所有行時(也就是沒有 WHERE 子句)

在通用表空間中刪除(DELETE)某個表中的所有行時(DB2 9 中新增)

對位於這兩類表空間中的表執行批量刪除(DELETE)時,DB2 不需要單獨尋址行,因此不會對它們計數 —— 但有三個例外:

啟用 DATA CAPTURE 時

調用 VALIDPROC 時

使用行級安全性時

但是,批量 DELETE 最常用於工作表或臨時表,它們極有可能體符合上述三種例外之一。

DB2 9 的一項新特性可允許您截斷表,從而對它執行 “重新初始化”(通過重新設置 High-Used Relative Byte Address [HURBA] 或者通過刪除並重新定義底層 VSAM 數據集 —— 非常類似於帶空 INPUT 數據集的 LOAD)。這與批量 DELETE 相類似,也不會將它們計入行數。

COUNT(*):問題 2

我們來看另一個實際生活中的不正確使用的例子:

程序員:使用 DB2 for z/OS 減少會話:第 1 部分:Prem Mehra 說過:“沒有比不執行的 SQL 性能更好的 SQL 了。”

我再次保證:我並不會在實際產生中使用這些例子。下面是程序員非常敬仰的信條:如果只有一個符合條件的行,則使用低速 CPU、路徑較短的 Searched SELECT,如果多於一個符合條件的行,則使用路徑較長的 CURSOR。

但是,讀取並計入行,然後再讀取行並處理它是不能解決問題的。不建議執行兩次讀取,即使分頁已經在緩沖池中。我不知道是多少次聽到這種方法了?只是因為,分頁可以在緩沖池中並不意外著可以隨意執行第二次讀取。由於 DB2 是一台重要、動態的維護機器,因此消除連接是一種可顯著降低 CPU 和 GET PAGE 開銷的方法。

那麼,針對這個問題有什麼更好的方法呢?程序員都在避免較高開銷的指針。因此,可以考慮一下這個問題:經常會遇到只有一個行的情況嗎?你說有百分之九十八的機率?那就先執行單體 SELECT。然後,如果接收到一條 -811 ("multiple rows returned to a Singleton Select") 錯誤消息,則打開指針。如果大多數時間都可以找到多個行,則立即打開指針,而不用擔心來自單體 SELECT 的反饋。換句話說,首先采用常普遍的方式,如果不行再執行 COUNT。

COUNT(*):問題 3

我們再看另一個實際生活中的例子:

程序員:使用 DB2 for z/OS 減少會話:第 1 部分:Prem Mehra 說過:“沒有比不執行的 SQL 性能更好的 SQL 了。”

此 COUNT 采用的邏輯如下:將 :hvcount 除以 10(屏幕上可顯示的行數),計算數據需要占用多少個屏幕。為什麼呢?這樣,每個屏幕(包括初始屏幕在內)都可以為用戶顯示 "Page 1 of n"。此處,我們可能會遇到 “不能刪除” 的情況。但是,如果用戶點擊 PF8 直到沒有行 / 屏幕時,是否可以采用更好的方式來確定有多少個 10 行的屏幕呢?

是的,首先應該問:“通常有多少個屏幕?”如果回答是一個屏幕或多個屏幕,則在閱讀之前不應計入這些行數。相反,打開指針,獲取行並在閱讀時計入這些行。如果在點擊第 11 行時到達 End of File,那麼應該可以知道答案,而不用執行 COUNT。並且,您已經刪除了 DB2 在執行 COUNT 時引入的所有 GET PAGE(或許是 READ I/Os)。

如果行數通常介於 11 和 30 呢?也應該讀取這些行,並在執行 FETCH 時計入它們。如果在讀取到第 31 行時計數已經達到 +100,則將這些行保存在屏幕顯示中間的某個位置(比如說 CICS 的 COMMAREA)。在第一頁上添加 "Page 1 of 3",然後刪除 PF8 顯示 "Page 2 of 3" 和 "Page 3 of 3" 所需的指令。

如果有 3 個以上頁面,則將用戶實際看到的內容保存在 COMMAREA 中(或任意位置)。然後,執行 COUNT。您已經將 COUNT 延緩到了最遲執行。您已經避免了大多數情況下的兩次讀取操作。最為重要的是,您的程序已經具備了良好的邏輯,其他人采用相同的方式編寫自己的程序。

結束語

對於日常需要使用 DB2 的用戶,以及對我的示例非常了解的用戶,我感覺感謝你們的支持和幫助,感謝你們分享了自己的思想和智慧。對於其他用戶,下一期將提供更多無用 SQL 的例子,並提供一些更加優秀的替換代碼的解決方案。敬請期待第 2 部分。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved