1. 程式人生 > >Oracle 12c 新特性:SQL Plan Directives與過量的動態取樣解析

Oracle 12c 新特性:SQL Plan Directives與過量的動態取樣解析

640?wx_fmt=gif640?wx_fmt=png

在 12c 中,優化器進行了較大的改變,推出了 Adaptive query optimization,從整體上說,Adaptive query optimization 可以看作如下兩部分:

640?wx_fmt=png

一部分是自適應執行計劃,一部分是自適應統計資訊。

這裡注意一下,
• Adaptive Plans – 是在第一次執行的時候,從default plan變成adaptive plan。
• Automatic Re-optimization -是在第二次執行的時候
• Statistics Feedback 以前叫Cardinality Feedback
• Dynamic Statistics 以前叫Dynamic Sampling
• SQL Plan Directives(SPD) 到目前12.1為止,你可以認為是動態取樣的持久化

好,我們今天討論的主題是最後一項,SQL Plan Directives(SPD)。

我們來一起看看 SPD。在2013年6月oracle官方的白皮書『Oracle Database 12c 中的優化器』中,提到:

SPD是根據從自動重新優化獲得的資訊自動建立的。SQL 計劃指令是優化器用於生成更優執行計劃的附加資訊。例如,當聯接在其聯接列中具有資料偏差的兩個表時,SQL 計劃指令可指導優化器使用動態統計獲得更準確的聯接基數估算。

所以,當 SQL 第一次執行時,oracle發現統計資訊估計的值和實際執行過程中發現值差距較大(misestimate),需要重新優化,就會生成SPD。也就是說,如果我們看到v$sql的is_reoptimizable欄位為Y,說明這個語句需要重新優化,在第二次執行的時候,或者類似sql執行的時候,SPD介入。在12.1中,SPD的唯一一個type,就是動態取樣(Dynamic sampling)。

Oracle會在misestimate的情況下,讓SPD介入。從目前收集到的資訊看,如下基數不準,會讓oracle認為misestimate。
• single table cardinality misestimate
• join cardinality misestimate
• query block cardinality misestimate
• group by cardinality misestimate
• having cardinality misestimate

我們來看這樣一個例子。

1

我建立了一個表,並生成一些資料,收集統計資訊

--初始化

conn test/test

drop table big_table;

create table big_table as

select 'iPhone' as product,

       mod(rownum, 5) as channel_id,

       mod(rownum, 1000) as cust_id

  from dual

connect by level <= 2000000

UNION ALL

select 'Motorola' as product,

       mod(rownum, 5) as channel_id,

       mod(rownum, 1000) as cust_id

  from dual

connect by level <= 10

UNION ALL

select 'Nokia' as product,

       mod(rownum, 5) as channel_id,

       mod(rownum, 1000) as cust_id

  from dual

connect by level <= 20401

UNION ALL

select 'Samsung' as product,

       mod(rownum, 5) as channel_id,

       mod(rownum, 1000) as cust_id

  from dual

connect by level <= 1000000;

exec dbms_stats.gather_table_stats(user,'BIG_TABLE',cascade=>true);

exit

2

刪除所有已經存在的SPD,並且清空 shared pool;

sqlplus  -S "/ as sysdba"

set pages 0

set line 10000

set echo off

set feedback off

set heading off 

set trimspool on

spool drop_spd.sql

select 'exec dbms_spd.DROP_SQL_PLAN_DIRECTIVE('||''''||DIRECTIVE_ID||''''||');' from dba_sql_plan_directives;

spool off

exit

sqlplus "/as sysdba"

@drop_spd

alter system flush shared_pool;

3

第一次執行這個 sql

--TestTime 1:

conn test/test

set line 1000

set pages 1000

set termout off

select /*+gather_plan_statistics*/

 cust_id, channel_id, product

  from big_table

 where product = 'Motorola'

   and channel_id = 1

 order by product

/

select* from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

640?wx_fmt=png

我們看到,即使收集了統計資訊,在執行過程中的 E-rows 和 A-rows 還是相去甚遠。

我們檢查 v$sql 的 is_reoptimizable 欄位,可以看到是Y。

col DIRECTIVE_ID for 999999999999999999999

col OWNER for a10

col object_name for a10

col SUBOBJECT_NAME for a10

col sql_text for a90

col spd_text for a45

col internal_state for a30

select sql_id, child_number, sql_text, is_reoptimizable from v$sql where sql_text like '%+gather_plan_statistics%big_table%'

/

640?wx_fmt=png

我們來看一下此時SPD的資訊,我們用到了2個檢視:dba_sql_plan_dir_objects和dba_sql_plan_directives。注意由於SPD是每隔15分鐘才刷入資料字典中持久化,我們手工進行flush一次,就不用等15分鐘,可以直接看了。

conn / as sysdba

exec dbms_spd.FLUSH_SQL_PLAN_DIRECTIVE;

select aa.directive_id,aa.owner,aa.object_name,aa.subobject_name,aa.object_type,

state,

extract(bb.notes, '/spd_note/internal_state/text()' ) internal_state,

extract(bb.notes, '/spd_note/spd_text/text()' ) as spd_text,

bb.type,bb.reason from dba_sql_plan_dir_objects aa,dba_sql_plan_directives bb

where aa.directive_id=bb.directive_id and aa.object_name in ('BIG_TABLE')

order by 10,1

/

640?wx_fmt=png

可以看到(點圖放大),SPD針對的是物件級,是我的 table BIG_TABLE 和其欄位PRODUCT和CHANNEL_ID。而當時用到的條件是: where product = ‘Motorola’ and channel_id = 1,通過實際執行,oracle認為這個表,和這2個欄位的資訊不準。

上圖中的幾個欄位稍微解釋一下:

a. SPD_TEXT是{EC(TEST.BIG_TABLE)[CHANNEL_ID, PRODUCT]}。Oracle認為你用來這2個欄位進行查詢,而這2個欄位缺少聯合統計資訊。這裡的E和C,以及可能出現其他的字元,解釋如下:
E – equality_predicates_only

C – simple_column_predicates_only
J – index_access_by_join_predicates
F – filter_on_joining_object

舉例來說,通常這樣的條件會認為如下的資訊misestimate:

from DEMO_TABLE where a=1 and b=1 and c=1 and d=1;
• {EC(DEMO.DEMO_TABLE)[A, B, C, D]}
• missing_stats, has_stats with extended statistics

from DEMO_TABLE where a+b=c+d;
• {E(DEMO.DEMO_TABLE)[A, B, C, D]}
• missing_stats, permanent as no statistics can help

from DEMO1 join DEMO2 using(KEY) where DEMO2.a=1;
• {(DEMO.DEMO1) – F(DEMO.DEMO2)}

b. INTERNAL_STATE 是NEW,表示是第一次,我們一會可以看看第二次執行的時候,會是如何。
NEW – 1st pass
MISSING_STATS – needs extended stats(gathered automagically)
HAS_STATS – extended stats have now been gathered(Intermediate State – new statements may still need SPD’s)
PERMANENT – extended stats have now been gathered(but SPD still needed because of != predicates)

c. TYPE是DYNAMIC_SAMPLING,表示下次執行時,如果此SPD介入,會執行動態取樣。

d. REASON表示為什麼oracle會認為這個語句需要SPD介入。因為oracle認為SINGLE TABLE CARDINALITY MISESTIMATE。
這個欄位的值有:
• single table cardinality misestimate
• join cardinality misestimate
• query block cardinality misestimate
• group by cardinality misestimate
• having cardinality misestimate

這個欄位要結合extract之後的notes,也就是上面的SPD_TEXT一起看。

好,我們再來看看,此時有沒有動態取樣介入。我們看看v$sql中,是否有DS_SVC hint的sql:

select sql_text from v$sql where sql_text like '%DS_SVC%'

/

640?wx_fmt=png

我們看到,此時沒有動態取樣的介入。

4

我們再來繼續測試,同樣的 SQL 語句,第二次執行的情況:

640?wx_fmt=png

我們看到此時的 E-rows 已經和 A-rows 一樣,也就是說,此時再次執行,cursor 還在快取的時候,直接使用statistics feedback,生成 child number 為1的 cursor。注意,此時動態取樣也還是沒介入的。

640?wx_fmt=png

5

如果我們 flush shared pool,我們來看看是什麼情況:

conn / as sysdba

alter system flush shared_pool;

--TestTime 1:

conn test/test

set line 1000

set pages 1000

set termout off

select /*+gather_plan_statistics*/

 cust_id, channel_id, product

  from big_table

 where product = 'Motorola'

   and channel_id = 1

 order by product

/

select* from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));


640?wx_fmt=png

我們看到,當同一個SQL,發生硬解析的時候,SPD介入,執行動態取樣。

我們再來看看是否在v$sql中有了動態取樣的資訊:
640?wx_fmt=png

可以看到已經有很多關於 DS_SVC 的動態取樣的語句了。

注意,此處的動態取樣,不是ADS(Automatic Dynamic Statistics)引起的,是SPD引起的。所以說,12c的動態取樣比11g要多的多,很大程度上,是SPD引起的。

11g的表如果收集的統計資訊,就不再會動態取樣。而 12c 中,即使表收集了統計資訊,還是會被 SPD 觸發,進行動態取樣。

我們再來看看SPD中的資訊:
640?wx_fmt=png

注意這裡的Internal狀態從NEW已經變成了MISSING_STATS。

到這裡,你可能已經意識到了SPD會造成比11g多的動態取樣,但是,是否只是影響同一個sql?

之前說過,SPD是針對物件級的,不是SQL級的,所以,當我有一個類似的sql觸發時,第一次硬解析的時候,SPD也會介入

6

我再執行一個“類似” SQL:

--TestTime 2:

conn test/test

set line 1000

set pages 1000

set termout off

select /*+gather_plan_statistics*/

 cust_id, channel_id, product

  from big_table

 where product = 'Nokia'

   and channel_id = 1

 order by product;

select* from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

640?wx_fmt=png

可以看到,也觸發了SPD,SPD指導優化器再次進行動態取樣。

而由於在第一次跑的時候,進行了動態取樣,且E-rows和A-rows之間差距小,Oracle認為它不需要is_reoptimizable:
640?wx_fmt=png

7

再執行另一個“類似” sql:

--TestTime 3:

conn test/test

set line 1000

set pages 1000

set termout off

select /*+gather_plan_statistics*/

 cust_id, channel_id, product

  from big_table

 where product = 'iPhone'

   and channel_id = 4

 order by product;

select* from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

也是同樣道理,SPD介入,執行動態取樣,但是is_reoptimizable是N.
640?wx_fmt=png

640?wx_fmt=png

但是,此時的DS_SVC,由於這些“類似”SQL的動態取樣,在v$sql中漸漸變多了。
640?wx_fmt=png

注:“類似”,是指語句中也有where product = ‘Motorola’ and channel_id = 1的語句。只要是這樣的語句,SPD都會介入。

我只是跑了4個,就已經出現了15個動態取樣的遞迴sql,在生產環境中,會更嚴重一些,如v$sql中總共9萬多個sql,其中7萬多個是這樣的帶DS_SVC的sql。

而由於12c中每次動態取樣都需要被result cache,此時就會出現Result cache的latch爭用。見Document 2002089.1High Latch Free Waits on ‘Result Cache: RC Latch’ In 12C when RESULT_CACHE_MODE = MANUAL

從上面的測試可以看出,SPD的介入應該是比較靠前的,當同一個語句再次執行的時候,如果已經快取,就採用Statistics Feedback,如果沒快取,在hard parse之初就介入了SPD,如果SPD的資訊還是missing,要求動態取樣,則在後面的執行的時候,都走了動態取樣;如果SPD中missing的資訊已經被收集,則SPD就從USABLE更新成SUPERSEDED,此時就不走動態取樣;

另外,當“類似”語句進入的時候,也是同樣道理。

用流程圖表示,基本就是下面這個圖的綠框部分:(整個圖是Adaptive query optimization)
640?wx_fmt=png

那麼,什麼樣的情況,才會讓SPD認為資訊已經收集齊了,STATE列從USABLE變成SUPERSEDED,INTERNAL_STATE列從MISSING_STATS變成HAS_STATS。從我的測試看,條件非常嚴格。不僅僅要收集所有列的直方圖,還要收集(CHANNEL_ID, PRODUCT)的extended stats.收集完之後,再次硬解析的時候,才會不走動態取樣。

select 

   dbms_stats.create_extended_stats

   ('TEST', 'BIG_TABLE', '(CHANNEL_ID,PRODUCT)') 

from dual;

EXEC DBMS_STATS.gather_table_stats('TEST', 'BIG_TABLE', method_opt => 'for all columns size 254');

select TABLE_NAME,COLUMN_NAME,HISTOGRAM from dba_tab_col_statistics where table_name='BIG_TABLE';

alter system flush shared_pool;

--TestTime 2:

conn test/test

set line 1000

set pages 1000

set termout off

select /*+gather_plan_statistics*/

 cust_id, channel_id, product

  from big_table

 where product = 'Nokia'

   and channel_id = 1

 order by product;

640?wx_fmt=png檢查SPD的狀態,可以看到變成如下了:

640?wx_fmt=png

此時,動態取樣不再進行。(由於收集了非常精確的統計資訊,E-rows完全等於A-rows)
640?wx_fmt=png

那麼既然SPD這麼容易造成動態取樣,且動態取樣容易有Result cache的latch(可以通過修改_optimizer_ads_use_result_cache=false來讓動態取樣不進result cache),且即使關閉了result cache的動態取樣,還是容易在v$sql中積累大量DS_SVC的hint的遞迴sql,消耗shared pool,我們如何來解決由SPD引起的動態取樣呢?

>>>解決方案<<<

1. 禁用Adaptive query optimization。OPTIMIZER_ADAPTIVE_FEATURES = FALSE,這是最大的總開關。
2. 禁用SPD產生新的directive:_sql_plan_directive_mgmt_control = 0(注意還要將原來已經存在的directive改成disable或者drop)
3. 禁用SPD的動態取樣:_optimizer_dsdir_usage_control = 0

>>>參考文獻<<<

Doc ID 2002089.1 High Latch Free Waits on 'Result Cache: RC Latch' In 12C 

Doc ID 2031605.1 Adaptive Query Optimization

Doc ID 2002108.1 Dynamic Sampling Level Is Changed Automatically in 12C

Doc ID 2033658.1 Dictionary Queries Running Slow in 12C PDBs

Doc ID 2097793.1 [INTERNAL]Commonly Reported Known Issues for Database

作者:何劍敏

投稿:有投稿、尋求報道意向技術人請聯絡 [email protected]

更多精彩請關注 “資料和雲” 公眾號

資源下載

關注公眾號:資料和雲(OraNews)回覆關鍵字獲取

2018DTCC , 資料庫大會PPT

2017DTC,2017 DTC 大會 PPT

DBALIFE ,“DBA 的一天”海報

DBA04 ,DBA 手記4 電子書

122ARCH ,Oracle 12.2體系結構圖

2017OOW ,Oracle OpenWorld 資料

PRELECTION ,大講堂講師課程資料

近期文章

640?wx_fmt=png

相關推薦

Oracle 12c 特性SQL Plan Directives過量動態取樣解析

在 12c 中,優化器進行了較大的改變,推出了 Adaptive query optimizat

Oracle Database 12c 特性RAC Cluster Hub Node 和 Leaf Node

Oracle Database 12c 新特性:RAC Cluster Hub Node 和 Leaf Node 在 Oracle Database 12c 的 Cluster 中引入了很多新特性和新概念,其中重複最多的幾個名詞除了 Flex Cluster、F

循序漸進Oracle 12c特性Sharding技術解讀

引言 資料庫構架設計中主要有 Shared Everthting、Shared Nothing 和 Shared Disk: Shared Everthting:一般是針對單個主機,完全透明共享 CPU/MEMORY/IO,並行處理能力是最差的,例如 Oracle

oracle 12c 特性之不可見字段

創建 oracl alt created 顯式 11g 不可見 插入數據 esc 在Oracle 11g R1中,Oracle以不可見索引和虛擬字段的形式引入了一些不錯的增強特性。繼承前者並發揚光大,Oracle 12c 中引入了不可見字段思想。在之前的版本中

Oracle 12C 特性之擴展數據類型(extended data type)

stand 特性 standard ava dbm har sco stat rac Oracle 12C 新特性-擴展數據類型,在12c中,與早期版本相比,諸如VARCHAR2, NAVARCHAR2以及 RAW這些數據類型的大小會從4K以及2K字節擴展至32K字節。只要

Oracle 12C 特性之在線重命名、遷移活躍的數據文件

查看 查詢 存在 data gop ddl ins aux 正在 Oracle 數據庫 12c 版本中對數據文件的遷移或重命名不再需要太多繁瑣的步驟,可以使用 ALTER DATABASE MOVE DATAFILE 這樣的 SQL 語句對數據文件進行在線重命名和移動。而當

Oracle 12C 特性之 db默認字符集AL32UTF8、PDB支持不同字符集

ans ica 允許 12c gbk 操作 utf contain sin 一、 db默認字符集AL32UTF8Specify the database character set when you create the database. Starting from Or

Oracle 12C 特性之 sqlplus查看History命令

let date 添加 version sys com delete 自動 ber 12c裏,Oracle推出了 History 命令,這很像 Shell 中的 history ,減少了重敲 SQL ,帶來了很多便利。1. 查看history幫助SQL> help h

Oracle 12C 特性之 恢復表

play 截斷 mman temp 租戶 ict total 重啟 修改表結構 RMAN的表級和表分區級恢復應用場景:1、You need to recover a very small number of tables to a particular point in t

Oracle 18c特性Schema-Only 帳號提升應用管理安全性

在 Oracle 18c 中,一個特殊型別的帳號被引入到資料庫當中,這特特性被稱為 Schema-Only 帳號,這個帳號通過 NO AUTHENTICATION 語句建立,沒有密碼,也就不允許直接登入,所以這種帳號型別是 純模式型別。 帳號不能直接

Oracle 12c 特性之varchar2長度最大值支援到32767

show parameter MAX_STRING_SIZE standard:代表12c之前的長度限制,即varchar2和nvarchar2 4是4000 bytes,raw是2000,且系統           預設是sta

Oracle 18c 特性動態 Container Map 增強 Application Container 靈活性

資料技術嘉年華等你來活動預告:11.16-17日,北京市東三環中路61號富力萬麗酒店,相聚資料技

ORACLE 12C特性——CDBPDB

  Oracle 12C引入了CDB與PDB的新特性,在ORACLE 12C資料庫引入的多租使用者環境(Multitenant Environment)中,允許一個數據庫容器(CDB)承載多個可插拔資料庫(PDB)。CDB全稱為Container Database,中文翻譯為資料庫容器,PDB全稱為Plugg

Oracle 12c特性

Oracle Database 12c前幾天正式釋出了,如果學習一個新版本的資料庫?我通常是從New Features Guide文件看起,先通覽文件的目錄,遇到感興趣的新功能點,就開始做實驗來驗證這個新功能。當然,這之前需要先把新版本的資料庫安裝好,先把新版本的全部文件下載

Oracle 12C 特性之表分割槽帶非同步全域性索引非同步維護(一次add、truncate、drop、spilt、merge多個分割槽)

實驗準備: -- 建立實驗表 CREATE TABLE p_andy (ID number(10), NAME varchar2(40)) PARTITION BY RANGE (id) (PARTITION p1 VALUES LESS THAN (10), PARTITION p2 VALUES LES

Oracle 12C 特性之線上重新命名、遷移活躍的資料檔案

Oracle 資料庫 12c 版本中對資料檔案的遷移或重新命名不再需要太多繁瑣的步驟,可以使用 ALTER DATABASE MOVE DATAFILE 這樣的 SQL 語句對資料檔案進行線上重新命名和移動。而當此資料檔案正在傳輸時,終端使用者可以執行查詢,DML以及 DD

Oracle 12C 特性之 PDB熱克隆

 說明:版本12.2.0.1 12c r1版本中 clone 一份PDB源庫需要開啟在read only只讀模式 , 在12c r2版本中引入了local undo mode, 源PDB在read/write 讀寫模式也可以 clone 。  local undo mo

Spark 3.0 特性 之 自適應查詢分割槽動態裁剪

Spark憋了一年半的大招後,釋出了3.0版本,新特性主要與Spark SQL和Python相關。這也恰恰說明了大資料方向的兩大核心:BI與AI。下面是本次釋出的主要特性,包括效能、API、生態升級、資料來源、SQL相容、監控和除錯等方面的升級。 ![](https://mmbiz.qpic.cn/mmbiz

Oracle 11g 特性 -- SQL Plan Management 示例

在之前的Blog 裡瞭解了Oracle 11g SQL Plan Management的理論,這篇Blog來演示一些具體的操作示例。 Oracle 11g 新特性 --SQL Plan Management 說明 官網說明: Using SQL Plan Managem

Oracle 11g 特性 -- SQL Plan Management 說明

一.概述 SQL 語句的SQL 執行計劃發生更改時,可能存在效能風險。 SQL 計劃發生更改的原因有很多,如優化程式版本、優化程式統計資訊、優化程式引數、方案定義、系統設計和SQL 概要檔案建立等。 在以前版本的Oracle DB 中引入了各種計劃控制技術(如儲存的大綱