上線快一個月,James 比較有時間,便想要針對 Stored Procedure 執行過久的問題進行調整。
之前因為趕著將案子如期上線,而這一段的執行時間也不會影響到簽核過程,所以針對 SQL 效能的部份並沒有花太多時間進行調整。
James 開啟 SQL Server 的 Query Analyzer(註1),並將 Excution Plan 選項打開,開始執行相關的 Stored Procedure,執行了一會兒,指令執行完畢,James 切換到 Excution Plan 視窗查看,並發現其中 sp_PO_resale_fcst 這一個程序的執行時間最久。(圖1)
圖1:Stored Procedure 執行 Excution Plan
James 發現,在這邊出現了 Bookmark Lookup,而且耗用了大部分的執行時間。(圖2)
圖2:Bookmark Lookup 耗用時間
於是 James 打開索引管理視窗,看看之前針對 sold_a 這個 Table 所建立的 Index,並沒有符合 Stored Procedure 中的查詢條件,而且每天重新 Create 的 sold_a Table 並沒有定義 Primary Key 以及叢集式索引。(圖3)
圖3:索引管理
於是 James 新增一個索引包含查詢條件中的兩個欄位,但執行後並沒有多大的改善。(圖4)
圖4:NonClustered Index
James 於是將新增的 Index 改為叢集式索引(Clustered Index)(圖5)(註2),並指定使用 IDX_sold_a_3 這個 Index,重新執行 Stored Procedure。
select isnull(sum(qty),0) from sold_a with (Index(IDX_sold_a_3)) ...
圖5:Clustered Index
再次執行完的結果,Bookmark Lookup 已經不見了,執行時間也順利的縮短(圖6),也確實使用到 IDX_sod_a_3 這個 Index(圖7),到此 James 終於可以比較放心了。
圖6:Stored Procedure 執行 Excution Plan
圖7:指定 Index
參考資訊:
2.善用索引提升查詢之效能 - Microsoft Performance Impact: Bookmark Lookup is Expensive - Even in Memory
註1:Query Analyzer 為 SQL Server 2000 的 SQL 工具
註2:SQL Server 2005 提供了 Convering Index 的功能,來輔助 Clusterd Index 只能有一個的不足
其實
索引一直是我多年以來的不滿
有多不滿呢
我開發的系統
從來不建索引
「那performance很差怎麼辦」
我才不管他呢
我是資料庫的「使用者」
我只負責下SQL
performance是資料庫自己的事
我在IBM VSAM要建索引
到了dBASE III Plus要建索引
到了RDBMS還要自已建索引
幾十年下來
資料庫系統自已都不改進了
還要使用者自已建索引
Performance不好還怪使用者沒建好索引
對於堅持認為索引是使用者的責任的人
我還有一個例子
使用了這麼久的Google
Google從來沒有要求使用者自己建過任何一個索引吧
相較於Google處理資料內容的多樣性
RDBMS面對的資料內容算是很「規律」了
而RDBMS可以很輕易地知道
「最常使用的是那些SQL指令」
「執行效能最差的是那些SQL指令」
知道了這兩項資訊
就該自動tunning執行效能
要自動建立索引也行
打完字發現寫了落落長一篇
真是老了
愛碎碎唸碎碎唸碎碎唸碎碎唸
所以才會有 DBA 這種角色出現...
antijava提到:
愛碎碎唸碎碎唸碎碎唸碎碎唸
我懂...
回應 antijava
在SQL Server 有資料庫引擎調校顧問(Database Engine Tuing Advisor, DTA), 有需要的大大可以學習使用看看;
但是當一個工具沒有百分之百正確時, 及對資源相當掌控時, 無法全自動化時需要人為適當判斷及參數.
以一個DBA對建立索引的認知來說:
當一個索引建立需要花費1個小時的時間, 若是離線建立則此段時間會造成相關表格無法交易, 若是線上建立則也會衝擊到資料庫效能, 因此需要人為去評估什麼是適當建立時間.
建立索引時需要使用大量的記憶體和暫存空間, 還有此索引所在的資料檔案的空間, 這些也是需要作業系統的配合才行.
以一段SQL 來說, 在上千筆的要格中, 讀取一筆資料或一個區間資料, 都要透過索引才能獲後良好效能, 除非是趨近於全表掃描, 才可以不需透過索引獲得良好效能; 所以當寫一段SQL進入資料庫要能有意識到用那個索引, 甚至會開立好索引, 才是下精準SQL, 才是一個好的使用者.
再以建立索引的時機, 理應是伴隨一段SQL的需求, 理想上是在新的SQL進入資料庫前, AP將此SQL知會DBA來評估建立索引; DBA 收到了此段SQL 在去評估相關表格及欄位(也就是人工的DTA工作), 及規劃建立資源, 時機, 及減輕對使用單位衝擊(公告維護時間).
在一般公司的環境上, 通常只有AP人員配置而沒有DBA人員配置, 往往是資深人員來充當資料庫設定的角色; 既然是資深人員對資源要有相當的掌控, 不是你我願不願意, 而是瞭解資料庫對AP人員來說是加分很大的.
charmmih提到:
在SQL Server 有資料庫引擎調校顧問(Database Engine Tuing Advisor, DTA), 有需要的大大可以學習使用看看;
別開玩笑了
我連索引都不建了
怎麼會去學這個呢
有時對有些不會建索引的程式開發大哥,
我心中會碎碎唸....
又是一位 "射後不理的大哥"...
你講的各項考量各項技術我都贊成,都沒意見
我的意見是
「這些該是RDBMS的工作還是使用者的工作」
經過幾十年的發展
RDBMS除了剛開始推出SQL語法
讓使用者不用自已在那裡seek來seek去之外
就再也不求長進了
我舉幾個很簡單例子
Web Server
FTP Server
SMTP Server
以上三個Server要處理搜尋的資料
某種程度上來看也不比DB Server單純到那裡去
但是
當你要Tunning以上三個Server的performance時
頂多只需要針對「整體環境」去改config
而不需要「依據資料內容」去調整設定
只有DBA這項職務
沒有聽過什麼WEBA, SMTPA, FTPA的職務
這究竟是RDBMS真的有那麼特別複雜
還是只是沒有人去challenge RDBMS的懶惰不長進
RDBMS已經發展到
連Left/Right/Inner/Outer Join來join去的sql指令都看得懂
連Query Analyzer和「調校顧問」都做得出來
難道
就沒辦法自己Tunning performance
要把責任推到使用者身上嗎
charmmih提到:
理應是伴隨一段SQL的需求, 理想上是在新的SQL進入資料庫前, AP將此SQL知會DBA來評估建立索引; DBA 收到了此段SQL 在去評估相關表格及欄位(也就是人工的DTA工作), 及規劃建立資源, 時機, 及減輕對使用單位衝擊(公告維護時間).
- 在一般公司的環境上,...(恕刪)
認同 charmmih 大的說法,DBA 的角色不僅在於提供系統良好的效能,對於資訊安全與稽核上的把關效用更大,也如同 charmmih 大第五點所提,現實環境中,很多都是校長兼撞鐘,湊活湊活,了解資料庫對 AP 開發人員來說,確實是加分,但這也暴露很大的風險,無從稽核...
antijava提到:
這些該是RDBMS的工作還是使用者的工作
antijava 大提出了一個相當值得思考的問題,RDBMS 主宰了企業應用幾十年了,效能為何一直都是企業應用系統的一個 issue!
也難怪乎 NoSQL 一再的被提出,不過就像當年的國語教育的推行一樣,我們逐漸忘了什麼是根本,什麼是自然...
「這些該是RDBMS的工作還是使用者的工作」
當你在學java時, 要深入研究JVM, 要學著耗用最少資源, 讓執行效能變快;
同時, 當我在學SQL時, 要深入研究RDMS, 要學著耗用最少資源, 讓執行效能變快;
只是, 你我有興趣深入研究的範疇不一樣而已.
經過幾十年的發展
RDBMS除了剛開始推出SQL語法
讓使用者不用自已在那裡seek來seek去之外
就再也不求長進了
當我是java門外漢時, 我也不知道JVM 長進什麼,
只知道是在OS層上會的VM, 好像效能方面不比其他原生程式.
當我沒有在此區塊耕耘時, 往往也是霧裏看花.
舉例來說, 以SQL資料庫最近幾年有下列進步, 有興趣google一下..
維護效能改善: always on ,HA, mirror,parition tabll/index, backup compression...
執行效能改善: clustered index, include index, where condition , table compression(row/page)...
才疏學淺, 未能詳列.
其實答案, 就在問題中....
Web Server
FTP Server
SMTP Server
以上三個Server要處理搜尋的資料
某種程度上來看也不比DB Server單純到那裡去
但是
當你要Tunning以上三個Server的performance時
頂多只需要針對「整體環境」去改config
這是系統管理範疇, 和資料庫一樣,
都要對 CPU, MEMORY, I/O Disk, Networking 的系統資源做設定,
只是一般 Server 用預設值就是可用狀態了....
而不需要「依據資料內容」去調整設定
當資料庫的資料成長量由 100MB -> 1GB -> 10GB -> 100GB -> 500GB 時,
那就要想想當初程式上線時, 壓力測試有沒有測到如此 ?
是不是要 「依據資料內容」去調整設定
ps: 先回答到此...
jamesjan提到:
SQL Server 2005 提供了 Convering Index 的功能,來輔助 Clusterd Index 只能有一個的不足
Convering Index(覆蓋索引)是一個觀念, 是SQL所用到的欄位均在索引中, 也就是索引就是基礎表格的經過排序的分身(小型表格), 此段SQL 並不會再需要去抓基礎表格, 舉例如下:
CREATE NONCLUSTERED INDEX IX_CUSTOMER_NAME ON CUSTOMER(NAME,ID);
select ID from CUSTOMER where NAME like '王%' (O)
select ID from CUSTOMER where NAME like '王%' order by TEL (X)
我認為索引有些演進, 值得關注並善加利用.
SQL 2000 每個表格某有一個叢集索引, 數個非叢集索引
SQL 2005 加入包含欄位(include field)
SQL 2008 加入條件子句(condition clause)
感謝 charmmih 的回覆,也讓我學習到很多
charmmih提到:
Convering Index(覆蓋索引)
筆誤, 是 Covering Index ...