中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Oracle 性能優化 之 游標及 SQL

發布時間:2020-08-10 07:16:16 來源:ITPUB博客 閱讀:291 作者:u_9a3ed7a37f8e4a 欄目:關系型數據庫

一、游標

我們要先說一下游標這個概念。

     

從 Oracle 數據庫管理員的角度上說,游標是對存儲在庫緩存中的可執行對象的統稱。SQL 語句是存儲在庫緩存中的,它是游標。除了它之外,還有 Oracle 的存儲過程也是存儲在庫緩存中的可執行對象,從 Oracle DBA 的角度上說,它也是游標。Oracle 也把它算為游標,在某些和游標相關的視圖中,也會顯示存儲過程的一些信息的。但從開發者的角度說,只有 SQL 語句才是游標。

二、關于游標的視圖

你的應用程序或許是用 Java、Pro*C 等語言開發的,也可能有中件間,等等,對于 DBA 來說,我們不必過多的關心這些。以一個常見的三層應用為例, 如下圖:


Oracle 性能優化 之 游標及 SQL


類似的圖我們在很多地方都可以看到,假設這是一個三層 J2EE 應用。客戶端調用的 Java 應用程序存放在中間的應用服務器層,應用程序的執行由應用服務器負責。


如上圖這段 Java 應用程序,它的執行就是應用應用服務器的任務。但是,當執行到 executeQuery ("select * from Test") 語句時,這條 Java 語句要求從數據庫服務器中查詢表 Test。發下圖:



這條語句的執行,是由數據庫服務器負責的。數據庫服務器只負責以最快的速度將 “Select * from test” 執行完畢。其他的它一概不負責。我們作為 DBA,只要保證 SQL 語句可以更快的執行就行了,至于應用程序邏輯方面的問題,不由我們負責。也就是說,作為 DBA,我們不必負責具體代碼的問題,我們只負責 SQL 語句的執行。每條送交 Oracle 執行的 SQL 語句,無論這條語句是你手動在 SQL*Plus 命令窗口中敲入的,還是應用服務器傳送給 Oracle 要求執行的,它們都以一樣的方式被傳遞到 Oracle 中,由服務器進程執行。這些 SQL 語句的執行情況、具體的執行計劃等數據資料會在一些視圖中被記錄下來,以供 DBA 追蹤問題、調優 SQL 的執行。


下面,我們就介紹一下這些相關 SQL 執行情況的視圖。我們再強調一個名詞,對于從任何地方傳遞給 Oracle 數據庫服務器要求執行的東西,我們都稱為游標。它主要包括 SQL 語句和 PL/SQL 程序段。


1. V$SQL


SQL_TEXT:SQL 語句的文本

SQL_FULLTEXT:SQL 語句的完全文本

SQL_ID



SHARABLE_MEM:游標所占共享內存


PERSISTENT_MEM:游標持續期所占用的 Fixed(固定)內存

 

RUNTIME_MEM:游標在運行期所占用的 Fixed(固定)內存


SORTS:游標完成的排序次數

LOADED_VERSIONS:游標在庫緩存所占的內存堆是否被加載


OPEN_VERSIONS:游標是否被鎖定。


USERS_OPENING:打開游標的會話數。也就是當正在緩存游標到 PGA 中的會話數。游標被執行三次后,就會被緩存到 PGA 中。此數值就加 1。


FETCHES:抓取的次數

 

EXECUTIONS:執行次數

PX_SERVERS_EXECUTIONS:以并行方式執行的總次數


END_OF_FETCH_COUNT:抓取全部行的次數


USERS_EXECUTING:當前正在執行此游標的會話數


LOADS:游標被加載或重新加載到庫緩存中的次數。游標只所以被重新加載有可能是游標無效或庫緩存內存不足。


FIRST_LOAD_TIME:游標被第一次被加載的時間。也就是生成執行計劃的時間


INVALIDATIONS:游標的無效次數

 

PARSE_CALLS:游標的解析次數,包括硬解析與軟解析

 

DISK_READS:游標執行了多少次物理讀

DIRECT_WRITES:游標直接寫的次數


BUFFER_GETS:邏輯讀的次數

 

APPLICATION_WAIT_TIME:應用程序的等待時間,單位微秒

 

CONCURRENCY_WAIT_TIME:并行的等待時間,單位微秒

 

CLUSTER_WAIT_TIME:Cluster 等待時間

 

USER_IO_WAIT_TIME:用戶 I/O 等待時間

 

PLSQL_EXEC_TIME:PL/SQL 執行時間

 

JAVA_EXEC_TIME:Java 執行時間

 

ROWS_PROCESSED:游標一共抓取了多少行。同樣的行,每抓取一次此列都會增加

 

COMMAND_TYPE:命令類型

 

OPTIMIZER_MODE:優化器模式

 

OPTIMIZER_COST:執行計劃的成本

 

OPTIMIZER_ENV:執行時的環境

 

OPTIMIZER_ENV_HASH_VALUE:環境的 HASH 值

 

PARSING_USER_ID:最先解析此游標的用戶的 ID

 

PARSING_SCHEMA_ID:最先解析此游標的方案 ID

PARSING_SCHEMA_NAME:最先解析此游標的方案 ID

KEPT_VERSIONS:是否使用 DBMS_SHARED_POOL 包將游標 Pin 到庫緩存中

 

ADDRESS:父游標句柄的地址

 

TYPE_CHK_HEAP:

 

HASH_VALUE:游標的 HASH 值

 

OLD_HASH_VALUE:老 HASH 值

 

PLAN_HASH_VALUE:執行計劃的 HASH 值。(上述三個 HASH 值并不相同)

 

CHILD_NUMBER:子游標數量

 

SERVICE:

 

SERVICE_HASH

 

MODULE:第一次解析游標的應用程序名。可以在應用程序中通過調用 DBMS_APPLICATION_INFO.SET_MODULE 設置。

 

MODULE_HASH:應用程序名的 HASH 值

 

ACTION:第一次解析時的動作名。可以在應用程序中通過調用 DBMS_APPLICATION_INFO.SET_ACTION 設置。

 

ACTION_HASH:動作名的 HASh 值

 

SERIALIZABLE_ABORTS:每個游標產生 ORA-08177 errors 錯誤(事務串行化無效)的次數。

 

OUTLINE_CATEGORY:大綱類型

 

CPU_TIME:游標解析、執行、抓取時所用的 CPU 時間。單位是微秒。

 

ELAPSED_TIME:游標解析、執行、抓取時所用的總時間。單位是微秒。

 

OUTLINE_SID:大綱會話的 SID

 

CHILD_ADDRESS:游標本身的地址

 

SQLTYPE:游標所用的 SQL 語言的版本

 

REMOTE:游標是否是遠端映像的

 

OBJECT_STATUS:對象狀態

 

LITERAL_HASH_VALUE:游標文本的 HASH 值

 

LAST_LOAD_TIME:執行計劃最后一次被加載到庫緩存中的時間。

 

IS_OBSOLETE:當子游標太多時,此子游標是否被荒廢。

 

CHILD_LATCH:保護游標的子閂編號

 

SQL_PROFILE:SQL 的概要文件

 

PROGRAM_ID:過程 ID

 

PROGRAM_LINE#

 

EXACT_MATCHING_SIGNATURE

 

FORCE_MATCHING_SIGNATURE

 

LAST_ACTIVE_TIME:最后一次使用執行計劃的時間。

 

BIND_DATA:綁定變量的信息


這個視圖中 DISK_READS、BUFFER_GETS、CPU_TIME、ELAPSED_TIME 這四個列在調優 SQL 語句時最為重要。在數據庫系統的速度不是太另人滿意時,如果你已經確定過了,不是其他方面的原因,而是 SQL 語句性能的問題,只是無法確定是那條、或那些條語句拖慢了整體的速度。那么此時選擇調優物理讀、邏輯讀最多的,或最耗 CPU 時間的 SQL 語句進行調節,往往可以取得今人滿意的性能增長。

     

我們也可以以 EXECUTIONS(執行次數)最多的 SQL 語句為調優對象。另外,PARSE_CALLS 是解析次數,對于此列值最多的 SQL 語句,我們可以看看是否可以降低語句的解析次數。

     

關于 SQL 調優,和程序的調優是一樣的。如果我們從事過代碼優化這樣的工作,就會知道,對于一個大型的應用程序來說調優的方法也是要從執行次數最多的那部分代碼、或從最消耗資源的代碼入手。

     

還有一個問題,就是文檔中關于這個視圖會經常提到一個概念:子游標與父游標。如果兩個游標的文本一模一樣,但由于環境不同,比如,游標所操作的表是不同用戶下的同名表,這兩個游標是不能共享執行計劃的。它們都有各自的執行計劃存在庫緩存中。這兩個游標就是子游標,Oracle 還會建立一個父游標,父游標中沒有執行計劃,它只是文本相同但執行計劃不同的所有游標的代表。

     

其實在庫緩存中,即使沒有文本相同的子游標,Oracle 會為每個游標都創建父游標。因為父游標是文本相同的子游標的代表嗎,所有文本相同的游標共享同一個父游標。

     

也就是說,只要你執行 SQL 語句,Oracle 都會在庫緩存中保存一父一子兩個游標。如果你執行了文本相同但環境不同因而不能共享執行計劃的 SQL 語句,那么一個父游標可能就對應多個子游標。

     

父游標沒有執行計劃,它只有一信息管理性數據,Oracle 添加它的目的就是為了管理文本相同的游標。有一個視圖是專門針對父游標的,就是 V$sqlarea。下面我們說一下這個視圖。


2. V$SQLAREA


V$SQLAREA 和 V$SQL 的列幾乎是一模一樣的。在 V$SQLAREA 中匯總了子游標的數據。如果有兩個語句:語句 A 和語句 B,它們文本一模一樣,但是由于環境不同沒有共享執行計劃,而是有各自的執行計劃。也就是語句 A 和語句 B 是同一父游標下的子游標。在 V$SQL 視圖中,因為它是顯示子游標的,所以語句 A 和語句 B 各占一行,假設語句 A 的 DISK_READS(物理讀)是 100,語句 B 的物理讀是 3000。V$SQLAREA 是顯示父游標信息的,語句 A 和語句 B 因為文本相同,它們兩個對應同一個父游標,在 V$SQLAREA 中占一行。在 V$SQLAREA 中,語句 A 和語句 B 父游標行中的 DISK_READS 就是 3100,也就是語句 A 和語句 B 的和。V$SQLAREA 中的其它列也是如此,都是 V$SQL 中相應子游標的合計。

     

有一個列是 V$SQL 中沒有的,就是:VERSION_COUNT,它是對應同一父游標的子游標的數量。如果這個數字太高,可能代表由于某些原因使本可以共享執行計劃的游標沒有共享。


3.V$open_cursor 與 Open_cursor 參數


這個視圖和參數涉及游標的打開。什么是游標的打開,就是在庫緩存中,用戶在軟、硬解析游標時,會在游標對象的句柄上加一個鎖,也就是 Library cache lock。在解析并執行完游標后,這個鎖并不會馬上去掉,而是會一直保留著,直到用戶發出了 Close 命令關閉游標時為止。我們在 SQL*Plus 命令窗口中發出的命令,在抓取完所有行后,SQL*Plus 將自動為我們發出 Close 命令來關閉游標。

 

當游標打開時,Library cache lock 將一直保持,這樣,即使庫緩存內存緊張,需要老化對象,也不會老化這些還正在加鎖的對象。因此,如果用戶不停的要求數據庫服務器打開游標、執行 SQL,但卻忘了關閉游標,這很容易耗盡共享池的內存。為此,Oracle 準備了一個參數,就是 Open_cursor,它的默認值在 9i 下是 50,在 10g 中是 300,也就是說,在 10g 下,每個會話最多只能同時打開 300 個游標。有了這個限制,就不用害怕用戶不停的打開游標但又不關閉它,而耗盡共享池內存了。

     

如果會話同時打開的游標數量超出了 Open_cursor 參數的限制,Oracle 將禁止會話打開新的游標。同時報出錯誤:ORA-01000: 超出打開游標的最大數 。

     

在用戶斷開會話的連接后,會話打開的這些游標將自動關閉。

     

V$open_cursor 視圖專用來查看當前會話打開的游標信息。它只能查看當前會話打開的游標。


4.CURSOR_SHARING 參數


如果應用程序中有很多類似下面這樣的 SQL 語句:


select * from 某表 where id=1;

select * from 某表 where id=2;

select * from 某表 where id=50;

     

等等,這些 SQL 語句嚴格來說是無法共享游標(也就是共享執行計劃)的,但是這些語句所需要執行計劃其實都是一樣的。無論你在表中查詢 ID 為 1 的行還是查詢 ID 為 100 的行,執行方式應該是一樣的。如果你想讓這樣的語句共享游標,那么,你可以改變 Cursor_sharing 參數的值。


此參有三個值:

  • ? EXACT:這個值是默認值。除非游標文本一模一樣,否則不會共享游標。

  • ? SIMILAR:這個最智能,如果游標只有條件中的數據值部分不同,并且庫緩存中原有游標的執行計劃對于新執行的 SQL 語句也是最優的,將不再為 SQL 語句創建新的游標,而是讓它共享庫緩存中原有的游標。

  • ? FORCE :不比較執行計劃是否最優,只要游標中除了條件中的數據值部分不同外,其他部分都相同,就會共享游標。

     

此參數可以在會話級修改,也就是可以使用 Alter session 修改它的值,這將只影響某一個會話,而不會影響其他會話。



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

邢台县| 顺义区| 贞丰县| 垣曲县| 岱山县| 巴林右旗| 宁河县| 鄯善县| 横峰县| 娱乐| 岢岚县| 炎陵县| 鹤庆县| 礼泉县| 新建县| 天长市| 勃利县| 上林县| 江川县| 迭部县| 大厂| 时尚| 西充县| 武定县| 佛冈县| 广州市| 松阳县| 元氏县| 黔东| 平江县| 青州市| 循化| 榕江县| 界首市| 花莲市| 高密市| 铜鼓县| 龙陵县| 榆社县| 安阳县| 甘洛县|