国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
什么時(shí)候oracle使用綁定變量性能反而更差

什么時(shí)候oracle使用綁定變量性能反而更差

作者: fuyuncat

來(lái)源: www.HelloDBA.com

當(dāng)我在做培訓(xùn)時(shí),在解釋綁定變量的好處時(shí),大家都比較容易理解。但是,對(duì)于并不是任何時(shí)候綁定變量都是最優(yōu)的。這一點(diǎn)很多人不是和理解。下面就討論一下在什么時(shí)候會(huì)出現(xiàn)綁定變量會(huì)使性能變差。

掃描成本和OPTIMIZER_INDEX_COST_ADJ

我們知道,在CBO模式下,Oracle會(huì)計(jì)算各個(gè)訪問(wèn)路徑的代價(jià),采用最小代價(jià)的訪問(wèn)路徑作為語(yǔ)句的執(zhí)行計(jì)劃。而對(duì)于索引的訪問(wèn)代價(jià)的計(jì)算,需要根據(jù)一個(gè)系統(tǒng)參數(shù)OPTIMIZER_INDEX_COST_ADJ來(lái)轉(zhuǎn)換為與全表掃描代價(jià)等價(jià)的一個(gè)值。這是什么意思呢?我們先稍微解釋一下這個(gè)參數(shù):OPTIMIZER_INDEX_COST_ADJ。它的值是一個(gè)百分比,默認(rèn)是100,取值范圍是110000。當(dāng)估算索引掃描代價(jià)時(shí),會(huì)將索引的原始代價(jià)值乘以這個(gè)百分比,將換算后的值作為與全表掃描代價(jià)比較的值。也就是說(shuō),當(dāng)這個(gè)值為100時(shí),計(jì)算出的索引掃描代價(jià)就是它的原始代價(jià):

COST_COM = COST_ORG * OPTIMIZER_INDEX_COST_ADJ/100

看以下例子:

SQL> create table T_PEEKING (a NUMBER, b char(1), c char(2000));
 
Table created.
 
SQL>
SQL> create index T_PEEKING_IDX1 on T_PEEKING(b);
 
Index created.
 
 
SQL> begin
  2    for i in 1..1000 loop
  3      insert into T_PEEKING values (i, ‘A‘, i);
  4    end loop;
  5
  6    insert into T_PEEKING values (1001, ‘B‘, 1001);
  7    insert into T_PEEKING values (1002, ‘B‘, 1002);
  8    insert into T_PEEKING values (1003, ‘C‘, 1003);
  9
 10    commit;
 11  end;
 12  /
 
PL/SQL procedure successfully completed.
 

注意,我們給索引字段B插入的值中只有3個(gè)distinct值,記錄數(shù)是1003,它的集的勢(shì)很高(1003/3=334。關(guān)于集的勢(shì)的計(jì)算,可以參考我的另外一篇文檔《關(guān)于集的勢(shì)的計(jì)算》。

 

SQL>
SQL> analyze table T_PEEKING compute statistics for table for all indexes for all indexed columns;
 
Table analyzed.
 
SQL>

我們看下索引掃描的代價(jià)是多少:

SQL> show parameter OPTIMIZER_INDEX_COST_ADJ
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_index_cost_adj             integer     100
 
SQL> delete from plan_table;
 
0 rows deleted.
 
SQL>
 
SQL> explain plan for select /*+index(a T_PEEKING_IDX1)*/ * from T_PEEKING a where b = :V;
 
Explained.
 
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id
  7  ;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=113
  TABLE ACCESS BY INDEX ROWID T_PEEKING
    INDEX RANGE SCAN T_PEEKING_IDX1
 
SQL>

 

再看全表掃描的代價(jià)是多少:

SQL> delete from plan_table;
 
3 rows deleted.
 
SQL>
SQL> explain plan for select /*+full(a)*/ * from T_PEEKING a where b = :V;
 
Explained.
 
SQL>
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id
  7  ;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=75
  TABLE ACCESS FULL T_PEEKING
 
SQL>

 

這時(shí),我們可以計(jì)算得出讓優(yōu)化器使用索引(無(wú)提示強(qiáng)制)的OPTIMIZER_INDEX_COST_ADJ值應(yīng)該 < ROUND(COST_FTS/COST_IDX*100) = ROUND(75/113*100) = 66,而大于66則會(huì)使用全表掃描:

 

SQL> alter system set OPTIMIZER_INDEX_COST_ADJ=67;
 
System altered.
 
SQL>
SQL> delete from plan_table;
 
2 rows deleted.
 
SQL>
SQL> explain plan for select * from T_PEEKING a where b = :V;
 
Explained.
 
SQL>
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=75
  TABLE ACCESS FULL T_PEEKING
 
SQL>
SQL>
SQL> alter system set OPTIMIZER_INDEX_COST_ADJ=66;
 
System altered.
 
SQL>
SQL> delete from plan_table;
 
2 rows deleted.
 
SQL>
SQL> explain plan for select * from T_PEEKING a where b = :V;
 
Explained.
 
SQL>
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=75
  TABLE ACCESS BY INDEX ROWID T_PEEKING
    INDEX RANGE SCAN T_PEEKING_IDX1

可以看出,在使用綁定變量時(shí),參數(shù)OPTIMIZER_INDEX_COST_ADJ對(duì)于是否選擇索引會(huì)有重要的影響。

 

這里我們暫且不討論索引掃描的原始成本是如何計(jì)算得出的。但是有一點(diǎn)很重要,在使用綁定變量時(shí),計(jì)算出的成本是平均成本。在我們上面的例子中,字段B的值只有3個(gè):"A"、"B""C",其中A最多,1003行中有1000行。因此,在索引上掃描值為A記錄的成本為1000/1003 * 索引全掃描成本 ≈索引全掃描成本,我們看下它的成本是多少:

SQL> alter system set OPTIMIZER_INDEX_COST_ADJ=100;
 
System altered.
 
SQL>
SQL> delete from plan_table;
 
2 rows deleted.
 
SQL>
SQL> explain plan for select /*+index(a T_PEEKING_IDX1)*/* from T_PEEKING a where b = ‘A‘;
 
Explained.
 
SQL>
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=336
  TABLE ACCESS BY INDEX ROWID T_PEEKING
    INDEX RANGE SCAN T_PEEKING_IDX1

 

可以看到,它的成本是336。因此索引的平均成本是(336 * 1003/1000) / 3 113,也就是使用綁定變量使的成本。而掃描其它兩個(gè)值"B""A"時(shí)代價(jià)就非常小。

SQL> alter system set OPTIMIZER_INDEX_COST_ADJ=100;
 
System altered.
 
SQL>
SQL> delete from plan_table;
 
3 rows deleted.
 
SQL>
SQL> explain plan for select /*+index(a T_PEEKING_IDX1)*/* from T_PEEKING a where b = ‘B‘;
 
Explained.
 
SQL>
SQL> select lpad(‘ ‘, 2*(level-1))||operation||‘ ‘||options||‘ ‘||
  2         object_name||‘ ‘||decode(id, 0, ‘Cost=‘||position) "Query
  3  Plan_Table"
  4      from plan_table
  5      start with id = 0
  6      connect by prior id = parent_id;
 
Query
Plan_Table
--------------------------------------------------------------------------------
SELECT STATEMENT   Cost=2
  TABLE ACCESS BY INDEX ROWID T_PEEKING
    INDEX RANGE SCAN T_PEEKING_IDX1

 

因?yàn)橛?jì)算的成本是平均成本(相對(duì)實(shí)際掃描某個(gè)值的成本,平均成本更接近全表掃描成本),因此在創(chuàng)建查詢(xún)計(jì)劃時(shí),使用綁定變量將更加容易受到參數(shù)OPTIMIZER_INDEX_COST_ADJ影響,特別是上面的這種情況(即索引字段的集的勢(shì)非常高時(shí))下,平均代價(jià)與實(shí)際掃描某個(gè)值代價(jià)相差非常遠(yuǎn)。這種情況下,OPTIMIZER_INDEX_COST_ADJ對(duì)不使用綁定變量查詢(xún)影響就非常?。ㄒ?yàn)樗饕鷥r(jià)不是比全表掃描成本大很多就是小很多),不管掃描哪個(gè)值,不使用綁定變量將更加容易選擇到合理的查詢(xún)計(jì)劃。

綁定變量窺視

在了解了參數(shù)OPTIMIZER_INDEX_COST_ADJ的作用后。再了解一個(gè)對(duì)查詢(xún)計(jì)劃,特別是使用綁定變量時(shí)會(huì)產(chǎn)生重大影響的特性:綁定變量窺視(Bind Variables Peeking)。

綁定變量窺視是9i以后的一個(gè)新特性。它使CBO優(yōu)化器在計(jì)算訪問(wèn)代價(jià)時(shí),將綁定變量傳入的值考慮進(jìn)去,從而計(jì)算出更合理的成本(否則,將會(huì)計(jì)算平均成本)。看下面例子:

SQL> conn sys/sys as sysdba
Connected.
SQL>
SQL> alter system set OPTIMIZER_INDEX_COST_ADJ=60;
 
System altered.
 
SQL> analyze table T_PEEKING compute statistics for table for all indexes for all indexed columns;
 
Table analyzed.
 
SQL>
SQL> set autot trace
SQL>
SQL> alter session set sql_trace = true;
 
Session altered.
 
SQL>
SQL> var v char(1)
SQL>
SQL> exec :v := ‘A‘;
 
PL/SQL procedure successfully completed.
 
SQL>
SQL> select * from T_PEEKING a where b = :V;
 
1000 rows selected.
 
SQL>
SQL> alter session set sql_trace = false;
 
Session altered.

TKPROF處理生成的trace文件。因?yàn)樵诖嬖诮壎ㄗ兞扛Q視時(shí),autotrace或者explain plan可能不會(huì)顯示正確的查詢(xún)計(jì)劃,需要tkprof來(lái)處理sql trace。

tkprof fuyuncat_ora_5352.trc aaa.txt

 

此時(shí)OPTIMIZER_INDEX_COST_ADJ60,根據(jù)上面的結(jié)論,似乎查詢(xún)計(jì)劃應(yīng)該選擇掃描索引。但是,這里給綁定變量賦了值"A",這時(shí),優(yōu)化器會(huì)“窺視”到這個(gè)值,并且在計(jì)算掃描成本時(shí)按照這個(gè)值的成本來(lái)計(jì)算。因此,得出的查詢(xún)計(jì)劃是全表掃描,而不是掃描索引,靠tkprof分析的結(jié)果:

select * 
from
 T_PEEKING a where b = :V
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch       68      0.01       0.07          0        406          0        1000
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       70      0.01       0.08          0        406          0        1000
 
Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS
 
Rows     Row Source Operation
-------  ---------------------------------------------------
   1000  TABLE ACCESS FULL T_PEEKING (cr=406 pr=0 pw=0 time=5052 us)
 
*************************************************************************

 

但是,綁定變量窺視對(duì)一條語(yǔ)句只會(huì)使用一次。就是說(shuō),在第一次解析語(yǔ)句時(shí),將綁定變量值考慮進(jìn)去計(jì)算成本生成查詢(xún)計(jì)劃。以后在執(zhí)行該語(yǔ)句時(shí)都采用這個(gè)查詢(xún)計(jì)劃,而不再考慮以后綁定變量的值是什么了。

SQL> conn sys/sys as sysdba
Connected.
SQL>
SQL>
SQL> set autot trace
SQL>
SQL> alter session set sql_trace = true;
 
Session altered.
 
SQL>
SQL> var v char(1)
SQL>
SQL> exec :v := ‘B‘;
 
PL/SQL procedure successfully completed.
 
SQL>
SQL> select * from T_PEEKING a where b = :V;
 
1000 rows selected.
 
SQL>
SQL> alter session set sql_trace = false;
 
Session altered.

 

再用tkprof分析生成的trace文件,看到盡管這里的值是"B",選擇索引掃描會(huì)更優(yōu),但分析結(jié)果中查詢(xún)計(jì)劃還是使用全表掃描:

select * 
from
 T_PEEKING a where b = :V
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0        340          0           2
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0        340          0           2
 
Misses in library cache during parse: 0
Optimizer mode: CHOOSE
Parsing user id: SYS
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      2  TABLE ACCESS FULL T_PEEKING (cr=340 pr=0 pw=0 time=1005 us)

 

因此,這種情況下使用綁定變量也會(huì)導(dǎo)致無(wú)法選擇最優(yōu)的查詢(xún)計(jì)劃。

 

綜上,我們可以得出一個(gè)結(jié)論:在對(duì)建有索引的字段(包括字段集),且字段(集)的集的勢(shì)非常大時(shí),使用綁定變量可能會(huì)導(dǎo)致查詢(xún)計(jì)劃錯(cuò)誤,因而會(huì)使查詢(xún)效率非常低。

 



本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
實(shí)踐實(shí)戰(zhàn):在PoC中的Oracle 12c優(yōu)化器參數(shù)推薦
ORA-00600: 內(nèi)部錯(cuò)誤代碼, 參數(shù): [qkacon:FJswpri], [0], [], [], [], [], [], []
Oracle數(shù)據(jù)庫(kù)優(yōu)化器的優(yōu)化方式
如何使用SQLPLUS分析SQL語(yǔ)句
Oracle案例:分析10053跟蹤文件-入門(mén)基礎(chǔ)
關(guān)于USE
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服