我們都知道在oracle中每條sql語句在執行之前都需要經過解析,這裡面又分為軟解析和硬解析。那麼這兩種解析有何不同之處呢?它們又分別是如何進行解析呢?oracle內部解析的步驟又是如何進行的呢?下面我們就這些話題進行共同**。
在oracle中存在兩種型別的sql語句,一類為ddl語句,他們是從來不會共享使用的,也就是每次執行都需要進行硬解析。還有一類就是dml語句,他們會根據情況選擇要麼進行硬解析,要麼進行軟解析。在oracle 8i ocp教材的023中1-12有說明sql語句的解析步驟,當一條sql語句從客戶端程序傳遞到伺服器端程序後,需要執行如下步驟:
? 在共享池中搜尋 sql 語句的現有副本
? 驗證 sql 語句的語法是否準確
? 執行資料字典查詢來驗證表和列的定義
? 獲取物件的分析鎖以便在語句的分析過程中物件的定義不會改變
? 檢查使用者訪問引用方案物件的許可權
? 確定語句的最佳執行計畫
? 將語句和執行計畫載入共享的 sql 區
這個先入為主的概念一直佔據著我的腦海,我認為硬解析就是上面幾個步驟。相對於硬解析,軟解析的步驟就是上面第一步找到現有sql語句的副本後,只需要驗證使用者是否有許可權執行就是了,這樣省略上面好幾個步驟,相對硬解析來說效能開銷就非常小了。即使是在論壇上和大家討論時,我也一直堅持這個看法。直到前一天看了tom的《effective oracle by design》中關於語句處理的章節後,我才知道這個自己一直堅持的觀點事實上是錯誤的。
事實上,在oracle中sql語句的解析步驟如下:
1、 語法檢測。判斷一條sql語句的語法是否符合sql的規範,比如執行:sql> selet * from emp;我們就可以看出由於select關鍵字少了乙個「c」,這條語句就無法通過語法檢驗的步驟了。
2、 語義檢查。語法正確的sql語句在解析的第二個步驟就是判斷該sql語句所訪問的表及列是否準確?使用者是否有許可權訪問或更改相應的表或列?比如如下語句:
sql> select * from emp;
select * from emp
error at line 1:
ora-00942: table or view does not exist
由於查詢使用者沒有可供訪問的emp物件,因此該sql語句無法通過語義檢查。
3、檢查共享池中是否有相同的語句存在。假如執行的sql語句已經在共享池中存在同樣的副本,那麼該sql語句將會被軟解析,也就是可以重用已解析過的語句的執行計畫和優化方案,可以忽略語句解析過程中最耗費資源的步驟,這也是我們為什麼一直強調避免硬解析的原因。這個步驟又可以分為兩個步驟:
(1)驗證sql語句是否完全一致。在這個步驟中,oracle將會對傳遞進來的sql語句使用hash函式運算得出hash值,再與共享池中現有語句的 hash值進行比較看是否一一對應。現有資料庫中sql語句的hash值我們可以通過訪問v$sql、v$sqlarea、v$sqltext等資料字典中的hash_value列查詢得出。如果sql語句的hash值一致,那麼oracle事實上還需要對sql語句的語義進行再次檢測,以決定是否一致。那麼為什麼oracle需要再次對語句文字進行檢測呢?不是sql語句的hash值已經對應上了?事實上就算是sql語句的hash值已經對應上了,並不能說明這兩條sql語句就已經可以共享了。我們首先參考如下乙個例子:假如使用者a有自己的一張表emp,他要執行查詢語句:select * from emp;使用者b也有一張emp表,同樣要查詢select * from emp;這樣他們兩條語句在文字上是一模一樣的,他們的hash值也會一樣,但是由於涉及到查詢的相關表不一樣,他們事實上是無法共享的。假如這時候使用者 c又要查詢同樣一條語句,他查詢的表為scott下的公有同義詞,還有就是scott也查詢同樣一張自己的表emp,情況會是如何呢?
sql> connect a/a
connected.
sql> create table emp ( x int );
table created.
sql> select * from emp;
no rows selected
sql> connect b/b
connected.
sql> create table emp ( x int );
table created.
sql> select * from emp;
no rows selected
sql> conn scott/tiger
connected.
sql> select * from emp;
sql> conn c/c
connected.
sql> select * from emp;
sql> conn/as sysdba
connected.
sql> select address,hash_value, executions, sql_text
2 from v$sql
3 where upper(sql_text) like 'select * from emp%'
4 /address hash_value executions sql_text
78b89e9c 3011704998 1 select * from emp
78b89e9c 3011704998 1 select * from emp
78b89e9c 3011704998 2 select * from emp
我們可以看到這四個查詢的語句文字和hash值都是一樣的,但是由於查詢的物件不同,只有後面兩個語句是可以共享的,不同情況的語句還是需要硬解析的。因此在檢查共享池共同sql語句的時候,是需要根據具體情況而定的。
我們可以進一步查詢v$sql_shared_cursor以得知sql為何不能共享的原因:
sql> select kglhdpar, address,
2 auth_check_mismatch, translation_mismatch
3 from v$sql_shared_cursor
4 where kglhdpar in
5 ( select address
6 from v$sql
7 where upper(sql_text) like 'select * from emp%' )
8 /kglhdpar address a t
78b89e9c 786c9d78 n n
78b89e9c 786ac810 y y
78b89e9c 786a11a4 y y
translation_mismatch表示sql游標涉及到的資料物件是不同的;auth_check_mismatch表示對同樣一條sql語句轉換是不匹配的。
(2、)驗證sql語句執行環境是否相同。比如同樣一條sql語句,乙個查詢會話加了/*+ first_rows */的hint,另外乙個使用者加/*+ all_rows */的hint,他們就會產生不同的執行計畫,儘管他們是查詢同樣的資料。我們下面就乙個例項來說明sql執行環境對解析的影響,我們通過將會話的 workarea_size_policy變更來檢視對同樣一條sql語句執行的影響:
sql> alter system flush shared_pool;
system altered.
sql> show parameter workarea_size_policy
name type value
workarea_size_policy string auto
sql> select count(*) from t;
count(*)
sql> alter session set workarea_size_policy=manual;
session altered.
sql> select count(*) from t;
count(*)
sql> select sql_text, child_number, hash_value, address
2 from v$sql
3 where upper(sql_text) = 'select count(*) from t'
4 /sql_text child_number hash_value address
select count(*) from t 0 2199322426 78717328
select count(*) from t 1 2199322426 78717328
可以看到由於不同會話workarea_size_policy設定得不同,即使是同樣一條sql語句還是無法共享的。通過進一步查詢v$sql_shared_cursor我們可以發現兩個會話的優化器環境是不同的:
sql> select optimizer_mismatch
2 from v$sql_shared_cursor
3 where kglhdpar in
4 ( select address
5 from v$sql
6 where upper(sql_text) = 'select count(*) from t' );on
y 通過如上三個步驟檢查以後,如果sql語句是一致的,那麼就會重用原有sql語句的執行計畫和優化方案,也就是我們通常所說的軟解析。如果sql語句沒有找到同樣的副本,那麼就需要進行硬解析了。
4、 oracle根據提交的sql語句再查詢相應的資料物件是否有統計資訊。如果有統計資訊的話,那麼cbo將會使用這些統計資訊產生所有可能的執行計畫(可能多達成千上萬個)和相應的cost,最終選擇cost最低的那個執行計畫。如果查詢的資料物件無統計資訊,則按rbo的預設規則選擇相應的執行計畫。這個步驟也是解析中最耗費資源的,因此我們應該極力避免硬解析的產生。至此,解析的步驟已經全部完成,oracle將會根據解析產生的執行計畫執行sql語句和提取相應的資料。
Oracle中的SQL語句
1.選擇部門30中的所有員工.select empno as 部門編號 ename as 員工名稱 job 員工工作 mgr 領導姓名 hiredate sal,comm deptno from emp where deptno 30 select from emp 2.列出所有辦事員 clerk ...
ORACLE 4 SQL語句解析
oracle 的硬解析和軟解析 提到軟解析 soft parse 和硬解析 hard parse 就不能不說一下oracle 對sql的處理過程。當你發出一條sql 語句交付oracle,在執行和獲取結果前,oracle對此sql 將進行幾個步驟的處理過程 檢查此sql 的拼寫是否語法。諸如檢查sq...
oracle中的SQL語句(一)
oracle中有些語句和標準sql有些細微差別。現在總結一些。oracle中的sql語句總結 1.建立資料表 create table scott director director id number 6 not null,name varchar2 10 not null,zhicheng va...