【《TOP》讀書筆記】<2> Key Concepts

viadeazhu發表於2010-09-05

這一章主要介紹整本書的一些概念性的詞句。

1.Selectivity and Cardinality

cardinality = selectivity . num_rows

2.Life Cycle of a Cursor

Open cursor
Parse cursor
Define output variables
Bind input variables
Execute cursor
Fetch cursor
Close cursor

3.Parse的各個步驟

Include VPD predicates:其實就是如果有行級的安全策略,那麼會有這一步產生的謂詞加入where條件裡。

Check syntax, semantics, and access rights:語法語義和許可權的檢查。

Store parent cursor in library cache:常常第一次執行時,連parent cursor都不在shared pool裡面,就要在library cache裡分配空間。此時決定一個parent cursor最重要的就是sqltext。

Logical optimization:就是再考慮一下SQL transformation所產生的更多可能的執行計劃。

Physical optimization:最佳化器選擇出最優的執行計劃,如果使用的是CBO,就根據對每種可能的執行計劃算出其cost,取其最小者。

Store child cursor in library cache:將child cursor存入shared pool的library cache中。child cursor最重要的就是執行計劃和執行環境。

接著,parent cursor可以透過v$sqlarea中查詢,child cursor可以使用v$sql。

例如,我在一個測試庫裡看到v$sqlarea並不包括所有的cursors,如果透過version_count欄位可以得出大部分和v$sql是相同的,但是有一點mismatch,至於為什麼,我也不知道。

SQL> select count(distinct SQL_ID),count(*) from v$sql;

COUNT(DISTINCTSQL_ID)   COUNT(*)
--------------------- ----------
                 2352       5466

SQL>  select count(distinct SQL_ID),count(*),sum(VERSION_COUNT) from v$sqlarea;

COUNT(DISTINCTSQL_ID)   COUNT(*) SUM(VERSION_COUNT)
--------------------- ---------- ------------------
                 2352       2352               5506

soft parse就是指只有前兩步執行。

hard parse就是指以上所有步驟都執行。

4.Shareable Cursors

parent cursor無法share常常是因為sqltext更改,例如literal sql。

child cursor無法share由兩種情況:1,執行計劃變了,2,執行的環境變了。

書中給出了個例子是在session級別更改了optimizer_mode,雖然執行計劃相同,但是還是產生了不同的child cursors(v$sql_shared_cursor.OPTIMIZER_MODE_MISMATCH不一樣)。

其實只要更改任意一個最佳化器的引數,也都類似,此時的表現是v$sql_shared_cursor.OPTIMIZER_MISMATCH不一樣。

有興趣的同學可以對v$sql_shared_cursor的每一列不一致的情況做個測試總結。

 

5.用bind variable的優點與bind variable graduation

當然是減少hard parses和節約shared pool的記憶體空間。

但是也有可能即使使用了bind variable,還是無法共享child cursor的情況,那就是繫結變數為varchar2欄位時,其最大值不一致時。

這個問題最近在我們的生產庫上出現了,很是頭疼,一個辦法是讓開發人員將所有的varchar2繫結變數都使用最大值為varchar2(4000)。

因為varchar2變數會根據其最大長度分成4種情況(bind variable graduation),如果你的SQL裡有10個varchar2的繫結變數,而且實際繫結的值的長度會不斷變化,那麼最多會產生4的十次方個child cursors。

這裡我show一個我們的產生巨多的child cursors的SQL:

> select sql_id,version_count from v$sqlarea
  2  where version_count>100
  3  order by version_count desc;

SQL_ID        VERSION_COUNT
------------- -------------
xxx                    7576

SELECT
distinct(m.max_length)
FROM v$sql s, v$sql_bind_metadata m
WHERE s.sql_id = 'xxx'
AND s.child_address = m.address
AND (m.datatype=1);

MAX_LENGTH
----------
        32
       128
      2000
      4000

如上透過檢視v$sql_bind_metadata我們可以看出varchar2欄位(即datatype=1)的四種分類的界限分別是32,128,2000和4000。

6.用bind variable的缺點與bind variable peeking

缺點當然是最佳化器看不到繫結的值,所以只有估算,有時無法得到最優的執行計劃,尤其是資料傾斜時。

bind variable peeking就是為了解決這個問題而在9i時引入的。但是此feature只會抓取第一次hard parse時的變數值來產生執行計劃,一次生成,一直使用。

extended cursor sharing(aks adaptive cursor sharing)這個11G new feature孕育而生,使得不同繫結變數值產生不同的執行計劃。

11G的ACS可以看我這篇文章詳細介紹:

http://space.itpub.net/15415488/viewspace-621535

 

 

 

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15415488/viewspace-672667/,如需轉載,請註明出處,否則將追究法律責任。

相關文章