(題圖來(lái)自Oracle VP , Sally Piao的攝影佳作,感謝攝影師授權)
編輯手記:感謝社區編輯李波協(xié)助,感謝崔華大神的精彩分享。在學(xué)習Oracle技術(shù)的過(guò)程中,總有一些時(shí)候你會(huì )對某個(gè)細節百思不得其解,而破解這些問(wèn)題則成為進(jìn)階路上的苦樂(lè )豐碑。這篇文章介紹了執行計劃在Shared Pool中的存儲位置探秘。
這兩天我一直在想一個(gè)問(wèn)題,那就是 Oracle 的執行計劃到底存儲在什么地兒?它會(huì )是一種什么樣的格式?
這里我試圖對這個(gè)問(wèn)題做一點(diǎn)我自己認為的解釋?zhuān)@個(gè)解釋可能是有問(wèn)題的。
朋友們在看這篇文章之前,應該首先熟悉如下的這張圖:
怎樣才叫熟悉這張圖呢?我認為驗證的方法就是看你是否能夠僅僅看著(zhù)這張圖,在1個(gè)小時(shí)的時(shí)間內把這張圖的內容解釋清楚。
這張圖也許能夠用來(lái)衡量你對 library cache 的了解程度。
我們現在做的測試其實(shí)就來(lái)源于上面這張圖:
首先執行一下下述的 sql:
SQL_testdb>select * from scott.emp;
接著(zhù)查一下上述 sql 在 library cache中的library cache object handle 的地址,一下兩種方式都可以獲取 SQL 語(yǔ)句父游標地址:
SQL_testdb>select address,sql_text from v$sqlarea where sql_text like ‘select * from scott.emp%’;
然后我們 dump 一下 library cache,注意這里level一定要大于等于8,否則看不到heap 0的內容:
SQL_testdb>alter session set events ‘immediate trace name library_cache level 11’;
Session altered.
SQL_testdb>oradebug setmypid
Statement processed.
SQL_testdb>oradebug tracefile_name
/cadrasu01/app/oracle/admin/testdb/udump/testdb_ora_4128918.trc
從上述trace文件中我們以 070000001CAE2C70 為關(guān)鍵字去查詢(xún),查詢(xún)結果如下:
注意看上述 library cache object 的類(lèi)型是 cursor,名字是 select * from scott.emp,它有一個(gè)子 cursor,其 library cache object handle 的地址是 70000001cae15e0。我們現在就以這個(gè)地址繼續搜索上述 trace 文件,搜到的內容如下:

從上述內容中我們可以看到,子 cursor 是沒(méi)有名字的,這個(gè)其實(shí)很正?!驗?Oracle 是通過(guò)先訪(fǎng)問(wèn)其 parent cursor 后才會(huì )來(lái)訪(fǎng)問(wèn)它。
另外,這個(gè)子 cursor 只有兩個(gè) data block,分別是 data block 0 和 data block 6,對應的就是上圖中的 heap 0 和 heap 6。
我首先排除掉 heap 0,理由如下:
The data block structure for a heap, stored in heap 0, contains a pointer to the first data block that is allocated for the heap, a status indicator, the pin under which the heap is loaded, and so on.
那么剩下的就只有一種可能,就是 Oracle 把 sql 的執行計劃存儲在了 heap 6里。
接下來(lái)我們 dump一下 heap 6 的內容:
SQL_testdb>oradebug setmypid
Statement processed.
SQL_testdb>alter session set events ‘immediate trace name heapdump_addr level 2, addr0x70000001cae1328′;
Session altered.
SQL_testdb>oradebug tracefile_name
/cadrasu01/app/oracle/admin/testdb/udump/testdb_ora_2859106.trc
從上述 trace文件中我們可以看到如下的內容:

上述 trace 文件的內容告訴我們 heap 6 實(shí)際上就是 sql area(這個(gè)和上圖中描述的 heap 6是 sql context 不盡相同),剩下的內容除了我們能看出包含了表 scott.emp 的各個(gè)字段的內容之外,其他的就看不懂了。
我猜測 Oracle 把 sql 的執行計劃存在了這個(gè) sql 的子 cursor 的 heap 6(也就是 sql area)中,只不過(guò)存儲的形式是編譯好的二進(jìn)制格式。
感謝 MOS,讓我找到了如下的論據,可以在某種程度上讓我自圓其說(shuō):
Parsing a cursor builds four different library cache structures, if they do not already exist, within the library cache:
1、parent cursor handle
2、parent cursor object, containing the child dependency list
3、child cursor handle, inserted in the child dependency list of the parent object
4、child cursor object, containing the compilation and run-time execution plan for the compiled SQL statement.
聯(lián)系客服