經常有客戶提說某個sql的執行計畫變差了,導致出現了效能問題,進而就問為啥解析出了新的
執行計畫。首先可以肯定突然出現了新的執行計畫表明sql進行了重新硬解析(注意重新硬解析不一定
產生新的執行計畫),那麼為啥好好的sql需要重新硬解析呢?今天我們就列舉幾種常見的原因:
1.自動收集統計資訊
為了保證sql的最佳執行效能,oracle需要找到乙個最優的執行計畫,基於cbo模式的優化器必須
要知道最新的統計資訊,例如條數,block數量,某個欄位的選擇率等,所以oracle每天凌晨都會執行一
個自動收集統計資訊的job,來收集那些變化超過10%的表的最新統計資訊,收集完成之後,理所當然
要對新來的sql進行使用,所以就需要進行硬解析。oracle 收集某個表統計資訊後預設是不會立即invalid
所有相關的cursor,因為這樣做太暴力,會引發硬解析相關的效能問題,所以巧妙的設計了一下,當某個相關sql執行的時候發現乙個依賴物件最近收集過統計資訊,便隨機的打個乙個時間戳,這個時間戳是
5個小時內某個時間戳,等到下次sql解析的時候若是發現了這個時間戳就會和當前時間進行比較,若是超過就說明已經到期,立即進行硬解析,否則還繼續進行軟解析。
2.沒有符合條件的child cursor 典型的如bind mismatch (其他原因可以參考v$sql_shared_cursor)
當某個sql使用了繫結變數的時候,oracle 會記錄cursor第一次硬解析時候的繫結變數的相關metadata,
當後續解析的時候便會進行檢查,若是發現繫結變數型別或長度不匹配就會進行重新解析,下面我們就用乙個小例子驗證一下:
create table maob_t as select from dba_tables ;
var b1 char(20);
exec :b1 := 'maob';
select count() from maob_t where table_name=:b1;
檢視cursor情況
select sql_id,child_number,first_load_time from v$sql where sql_text like '%count%maob_t%'
4v22rgk83gjnc 0 2017-12-15/22:52:46 <
把繫結變數型別變成varchar2,sql文字不變,再次執行:
var b1 varchar2(20);
exec :b1 := 'maob';
select count(*) from maob_t where table_name=:b1;
執行上述語句後再次檢視
select sql_id,child_number,first_load_time from v$sql where sql_text like '%count%maob_t%'
4v22rgk83gjnc 0 2017-12-15/22:52:46
4v22rgk83gjnc 1 2017-12-15/22:52:46
可以看到已經有兩個只cursor,進一步檢視cursor不能share的原因:
select sql_id,child_number,bind_mismatch from v$sql_shared_cursor where rownum<10 and sql_id='4v22rgk83gjnc'
sql_id,child_number bind_mismatch
4v22rgk83gjnc 0 n
4v22rgk83gjnc 1 y <<
可以看到由於繫結變數的原因造成的mismatch,所以硬解析產生了第二個子cursor。
3.oracle11g 提供了自適應游標功能(adaptive cursor sharing),如果表上的字段存在直方圖並且資料存在傾斜的場景下,那麼對於傳入不同的資料就會造成oracle重新嘗試硬解析。具體內容,可以參考另外一篇部落格。
4.cursor 已經被ageout 記憶體
我們都知道,oracle 對於記憶體管理機制和很多os管理記憶體機制一樣,都採用了lru(least recently used,最近最少使用)演算法,
cursor作為一種library cache 中的物件也不例外,若是某個sql解析需要share pool記憶體時,發現free list 上並沒有合適大小的記憶體塊(chunk)
就會觸發清理機制,那麼之前cursor 申請的chunk就依據lru演算法規則被清理掉,這種就是age out,需要注意的是,這個是oracle的
機制,並不是os上的swap機制,一旦某個cursor的被ageout出shared pool,那麼下次執行這個sql的時候就是重新硬解析。
5.除了上述幾種oracle自身的機制造成重新硬解析之外,也存在人為因素操作造成的可能
例如人為收集統計資訊,人為執行了flush shared_pool 操作,手工呼叫dbms_shared_pool.purge 來清理某個cursor
執行了ddl 語句等。
json解析的幾種方式 解析物流分揀常見的幾種方式
在物流配送中,由於倉庫的規模 訂單數量和貨物種類不同,分揀方式也不同。但是,常用的分揀方法大致可分為三類 人工分揀 半自動機械分揀裝置和分揀機自動分揀。今天我們就來分析一下現代物流分揀幾種方式的區別和特點是什麼?它是物流分揀最初的形態,以人工為主,僅需較小的裝置投入。但隨著電商的發展,訂單分揀量迅速...
mysql 常見的幾種日誌設定
mysql日誌是我們需要掌握的知識,下面就為您介紹幾個最常見的mysql日誌型別,如果您對mysql日誌方面感興趣的話,不妨一看。1 錯誤日誌 記錄啟動 執行或停止mysqld時出現的問題。my.ini配置資訊 enter a name for the error log file.otherwis...
mysql中常見的幾種索引
主鍵索引 資料列不允許重複,不允許為null,乙個表只能有乙個主鍵。唯一索引 資料列不允許重複,允許為null值,乙個表允許多個列建立唯一索引。可以通過 alter table table name add unique column 建立唯一索引 可以通過 alter table table na...