楊國勛
摘 要 在軟件應用系統設計和開發(fā)的過程中,容易被設計者所忽視的就是如何通過增加數據庫SQL語句共享來提高系統的整體性能,本文通過深入研究Oracle數據庫中SQL語句的解析過程,分析了SQL語句不能共享的主要原因,并給出如何增加SQL語句共享率的解決方案。
關鍵詞 SQL語句共享;軟解析;硬解析
中圖分類號:TP311 文獻標識碼:A 文章編號:1671-7597(2014)22-0069-01
Oracle數據庫是目前在中大型軟件項目中應用最為廣泛的數據庫之一,在這樣一些項目中需要處理的數據量是非常巨大的,而且用戶對應用系統的性能要求比較高。提高系統的性能一方面是需要有一個良好的架構設計,另一方面則是要提高底層數據庫系統的性能。數據庫性能的提升需要由經驗豐富的DBA來配置和維護,但更重要而且是容易被忽視的是程序員在編寫代碼時需要提高數據庫系統的SQL語句共享率,避免不必要的SQL語句硬解析,從而降低系統在進行SQL語句解析花費的時間和資源。
1 SQL語句解析過程
Oracle處理客戶端應用程序提交過來的SQL語句主要分為4個階段,SQL語句解析、參數綁定、執(zhí)行和獲取結果,其中SQL語句解析是其中非常重要的一個階段,理解這個階段的處理過程對于提高應用系統整體性能有很好的幫助。
在SQL語句的解析階段,Oracle會進行如下操作:
檢查SQL語法錯誤:檢查SQL語句中的關鍵字是否有拼寫錯誤,順序和位置是否正確等。
檢查SQL語義錯誤:檢查該SQL語句引用的對象是否存在,提交SQL語句的用戶是否具有訪問該對象的權限等。
SQL共享語句查詢:Oracle數據庫服務器管理程序會先在服務器會話緩存用戶全局區(qū)(UGA)中查詢是否有此SQL語句對應的已打開的游標(Open Cursor),如果有則通過已打開游標中的指針找到在服務器共享池(Shared Pool)中的此SQL語句對應游標句柄并執(zhí)行,此時不需要對語句進行解析,因為打開的游標已經被解析,而且游標句柄已經存在于服務器共享池的庫緩存(Library Cache)中。
如果游標被關閉,則游標的信息會被保存在會話關閉游標的緩存中,此緩存的大小是由參數SESSION_CACHED_CURSORS決定的。當系統在UGA中沒找到SQL語句對應的已打開的游標,則會在已關閉游標緩存中查詢,如找到匹配的已關閉游標,則會重新打開此游標,通過此游標可以直接執(zhí)行SQL語句而不需要重新解析。
如果系統在UGA中沒找到此SQL語句的游標,則會根據SQL語句生成的Hash值在Shared Pool中的Hash鏈中查詢是否有此SQL語句對應的游標句柄,如果此游標句柄能夠找到且游標的其他信息沒有丟失,則可以執(zhí)行此SQL語句,此次查詢過程被系統記錄為一次解析,但不是真的解析,因此這個過程也被稱為軟解析。
硬解析:如果此SQL語句在UGA和Shared Pool中都沒有找到匹配的游標,則Oracle服務器系統需要在Library Cache中為此SQL語句創(chuàng)建一個父游標(parent cursor)和一個子游標(child cursor)。父游標中包含了SQL文本和對應的Hash值,父游標的信息可以通過視圖v$sqlarea查詢。子游標中包含了使得這個SQL可以執(zhí)行的所有相關信息,如執(zhí)行權限、優(yōu)化器設置和執(zhí)行計劃等。子游標的信息可以通過視圖v$sql進行
查詢。
2 SQL語句無法共享原因分析
通過對SQL語句在Oracle中的解析過程研究可以知道,SQL語句無法共享主要是由兩個原因造成,父游標無法共享以及子游標無法共享。
1)父游標無法共享。
父游標能夠共享的前提條件是SQL語句對應的Hash值要一致,Oracle系統在生成SQL語句Hash值的時候是會區(qū)分大小寫和空格,如下面幾條SQL語句雖然查詢含義一樣,但寫法沒有統一使得Hash值不一致而造成SQL語句無法共享。
select * from tb_student where id=1
select * from TB_STUDENT where id=1
select * from tb_student where id=1
2)子游標無法共享。
當SQL語句及其Hash值一致時就可以共享父游標,但有時會因為種種原因使得子游標無法共享,此時同一個父游標會有多個子游標,子游標的個數可以通過視圖v$sqlarea的version_count字段查詢處理。在實際的項目中,要盡量避免version_count過高的情況。子游標無法共享的一個常見原因是綁定變量不一致,這里的變量不一致,有可能是變量名不一致,也有可能是變量對應的數據類型的長度不一致,例如,對于字符類型的字段,進行綁定變量的時候,如果該變量值小于32字節(jié)的話,第一次會使用32字節(jié)的緩沖區(qū),第二次執(zhí)行這個SQL的時候,如果該值小于32字節(jié),那么可以共享這個子游標,如果大于32字節(jié)就無法共享,此時會在同一父游標下創(chuàng)建一個新的子游標,同時分配128字節(jié)的緩沖區(qū)。子游標另外一個無法共享的常見原因是SQL語句查詢選擇的優(yōu)化器模式不一致。子游標無法共享的原因可以通過查詢視圖v$sql_shared_cursor進行分析。
3 增加SQL語句共享率
通過上述分析,要增加SQL語句共享率,提高系統的整體性能可以從以下幾方面入手:
1)SQL語句在文本上必須完成相同,包括空格、換行、大小寫都必須完全相同,因此在項目組中要制定SQL語句的書寫規(guī)范,使得不同的程序員在編寫程序時按照統一的SQL語句規(guī)范來書寫,增加SQL語句共享,減少SQL語句硬解析的次數,提高應用程序的執(zhí)行效率。
2)在書寫SQL語句的時候盡量使用綁定變量的方式,并且保證變量名和變量數據類型字段長度一致。在進行SQL語句查詢時,盡量選擇一致的優(yōu)化器模式。
3)設置SESSION_CACHED_CURSORS參數為一個恰當的值,從而保證被關閉的游標能在服務器緩存中保存一段時間,增加SQL語句共享的幾率。
參考文獻
[1]張江.Oracle數據庫的性能優(yōu)化策略淺析[J].現代計算機(專業(yè)版), 2012(36).
[2]趙琛.Oracle服務器性能影響因素分析與優(yōu)化[J].電腦編程技巧與維護,2011(20).endprint