1. 程式人生 > >直方圖;繫結變數窺探;自適應遊標

直方圖;繫結變數窺探;自適應遊標

搭建環境

構建一個表
CREATE TABLE TEST2 AS SELECT * FROM DBA_OBJECTS;
UPDATE SET OBJECT_ID = 11111 WHERE ROWNUM <=50000;
建立索引:
CREATE INDEX IND_TEST2_OBJECT_ID ON TEST2(OBJECT_ID);
收集統計資訊,不收集直方圖
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'SCOTT',TABNAME=>'TEST2',ESTIMATE_PERCENT=>100,cascade=>true,method_opt => 'for all columns size 1');
SQL> SELECT OBJECT_ID FROM TEST2 WHERE OBJECT_NAME = 'TEST';
 OBJECT_ID
----------
     52694

毋庸置疑index range scan
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=11111;
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=52694;

收集直方圖

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
                                tabname => 'TEST2',
                                estimate_percent => 100,
                                method_opt => 'for all columns size skewonly',
                                no_invalidate => FALSE,
                                degree => 1,
                                cascade => TRUE);
END;
/

全表掃描
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=11111;
index range scan
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=52694;

但當直方圖碰上繫結變數:
9i,10g
alter system flush shared_pool;
var a number;
exec :a := 52694;
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1
SQL> select sql_id,child_number from v$sql where sql_text like 'SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a%';
SQL_ID        CHILD_NUMBER
------------- ------------
22gd2utvtttmj            0
SQL> select * from table(dbms_xplan.display_cursor('22gd2utvtttmj',0,'advanced peeked_binds'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  22gd2utvtttmj, child number 0
-------------------------------------
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a

Plan hash value: 3600962442

-----------------------------------------------------------------------------------------
| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                     |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |                     |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| IND_TEST2_OBJECT_ID |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / 
[email protected]
$1 Outline Data ------------- /*+ BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS OPTIMIZER_FEATURES_ENABLE('10.2.0.1') ALL_ROWS OUTLINE_LEAF(@"SEL$1") INDEX(@"SEL$1" "TEST2"@"SEL$1" ("TEST2"."OBJECT_ID")) END_OUTLINE_DATA */ Peeked Binds (identified by position): -------------------------------------- 1 - :A (NUMBER): 52694 Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID"=:A) Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - (#keys=0) COUNT(*)[22] ==================================================================================================================
exec :a := 11111;
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> select sql_id,child_number from v$sql where sql_text like 'SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a%';

SQL_ID        CHILD_NUMBER
------------- ------------
22gd2utvtttmj            0

SQL>  select * from table(dbms_xplan.display_cursor('22gd2utvtttmj',0,'advanced peeked_binds'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  22gd2utvtttmj, child number 0
-------------------------------------
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a

Plan hash value: 3600962442

-----------------------------------------------------------------------------------------
| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                     |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |                     |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| IND_TEST2_OBJECT_ID |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / [email protected]$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "TEST2"@"SEL$1" ("TEST2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :A (NUMBER): 52694

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]
從上面可以發現,由於繫結變數只有在硬解析的時候才回去“窺探”,所以硬解析時候窺探的繫結變數的值就決定了整個執行計劃,即使發生改變oracle的也不管。這個就比較坑爹了。
11g
SQL> var a number;
SQL> exec :a := 52694;
PL/SQL procedure successfully completed.
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1
SQL>  SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1
SQL>  SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
         1

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced peeked_binds'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  67wpp1xx1jsb4, child number 0
-------------------------------------
 SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a

Plan hash value: 3600962442

-----------------------------------------------------------------------------------------
| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                     |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |                     |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| IND_TEST2_OBJECT_ID |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / [email protected]$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "TEST2"@"SEL$1" ("TEST2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :A (NUMBER): 52694

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

==============================================================================
SQL> exec :a := 11111;
PL/SQL procedure successfully completed.
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;
  COUNT(*)
----------
     50000
SQL> select sql_id,child_number from v$sql where sql_text like 'SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a%';

SQL_ID        CHILD_NUMBER
------------- ------------
22gd2utvtttmj            0
22gd2utvtttmj            1
22gd2utvtttmj            2

SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;

  COUNT(*)
----------
     50000

SQL>  select * from table(dbms_xplan.display_cursor(null,null,'advanced peeked_binds'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  22gd2utvtttmj, child number 2
-------------------------------------
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a

Plan hash value: 1970853342

---------------------------------------------------------------------------------------------
| Id  | Operation             | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                     |       |       |    48 (100)|          |
|   1 |  SORT AGGREGATE       |                     |     1 |     5 |            |          |
|*  2 |   INDEX FAST FULL SCAN| IND_TEST2_OBJECT_ID | 49956 |   243K|    48   (3)| 00:00:01 |
---------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / [email protected]$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_FFS(@"SEL$1" "TEST2"@"SEL$1" ("TEST2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :A (NUMBER): 11111

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("OBJECT_ID"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]


49 rows selected.

SQL>  exec :a := 52694;

PL/SQL procedure successfully completed.

SQL> SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a;

  COUNT(*)
----------
         1

SQL>  select * from table(dbms_xplan.display_cursor(null,null,'advanced peeked_binds'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  22gd2utvtttmj, child number 1
-------------------------------------
SELECT count(*) FROM TEST2 WHERE OBJECT_ID=:a

Plan hash value: 3600962442

-----------------------------------------------------------------------------------------
| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                     |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |                     |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| IND_TEST2_OBJECT_ID |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / [email protected]$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "TEST2"@"SEL$1" ("TEST2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :A (NUMBER): 75819

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

從上面可以看出來,11g之後,oracle引入自適應遊標,oracle會根據繫結變數值得改變而改變執行計劃了。這才是我們需要的。

相關推薦

直方圖變數窺探適應遊標

搭建環境 構建一個表 CREATE TABLE TEST2 AS SELECT * FROM DBA_OBJECTS; UPDATE SET OBJECT_ID = 11111 WHERE ROWNUM <=50000; 建立索引: CREATE INDEX IND

Oracle 變數窺探

Bind Peeking是Oracle 9i中引入的新特性,一直持續到Oracle 10g R2。它的作用就是在SQL語句硬分析的時候,檢視一下當前SQL謂詞的值 ,以便生成最佳的執行計劃。而在oracle 9i之前的版本中,Oracle 只根據統計資訊來做出執行計劃。

SQL Profiles的force_match引數在不改變程式碼的情況下解決沒有使用變數的問題

How To Use SQL Profiles for Queries Using Different Literals Using the Force_Match Parameter of DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (Doc ID 1253696.1)

jQuery on() 方法 為選定已存在元素和未來元素標準事件和定義事件

很有必要說說jQuery的on方法,這個方法存在大乾坤大奧祕,主要注意兩點: 1、為已存在元素和未來元素(動態新增元素)繫結處理函式。 2、自定義一個非標準的事件並繫結處理函式。 定義和用法 on() 方法在被選元素及子元素上新增一個或多個事件處理程式。 自 jQuery 版本 1.7 起,on()

檢視oracle中未使用變數的sql語句

資料庫版本:11.2.0.4 查詢語句: with force_mathces as (select l.force_matching_signature mathces, max(l.sql_id || l.child_number) max_sql_

Nginx 內建變數

Nginx作為一個成熟、久經考驗的負載均衡軟體,與其提供豐富、完整的內建變數是分不開的,它極大增加了對Nginx網路行為的控制細度。這些變數大部分都是在請求進入時解析的,並把他們快取到請求cycle中,方便下一次獲取使用。首先來看看Nginx對都開放了那些API。 參看下表

mybatis批量分批次插入oracle資料庫,報ORA-01745: 無效的主機/變數名...

方法一:迴圈呼叫插入單條記錄的方法,效率真心讓人捉急 (3萬條資料,快三分鐘)     public int saveGwghidlist1(List<Gwghid> list) {                  int xh=0;         dele

angular/ionic中對img、iframe等的src進行動態變數的問題解決

例如以下程式碼: 對應的html頁面中是這樣:<iframe class=“filling” [src] = “iframe”> 在這裡直接對src進行動態繫結變數就會出現:unsafe value used in a resource URL co

spring 中@ModelAttribute變數中文亂碼的解決辦法

網上找了一些方法: 方法一 在專案的web.xml中配置spring的Character Encoding Filter <!-- Servlet Encoding Start --> <filter> <filter

python cx_oracle 變數

insert into tlcb_collect_f5 values(:stime,:virtual_servers,:default_pool_name,:ipaddr,:port,:AVAILABILITY_STATUS,:ENABLED_STATUS,:POOL_MEMBER_STATUS);

powershell指令碼,命令列引數傳值,並變數的例子

        這是小技巧文章,所以文章不長。但原創唯一,非常重要。我搜了下,還真沒有人發 powershell怎樣 【命令列 引數 繫結】,所以我決定寫成部落格。 搜尋關鍵字如下: powershell 命令列 引數 繫結 powershell 傳入 引數 powershell 傳遞 引數 p

oracle動態sql以及變數

        實現動態SQL有兩種方式:DBMS_SQL和本地動態SQL(EXECUTE IMMEIDATE) 。 oracle從8代開始就提供了新的執行動態sql的功能:execute immeidate v_sql using *** into ***; 本地動態

sqlplus之使用變數

oracle將已解析、已編譯的SQL連同其他內容儲存在共享池(shared pool)中,這是系統全域性區(System Global Area,SGA)中一個非常重要的共享記憶體結構.繫結變數(bind variable)是查詢中的一個佔位符。例如,要獲取員工編號7369的

android6.0下SETTING_VERSION無法變數

在android6.0 RK3288這個平臺,碰到這樣的一個問題,在帶有Android.mk的目錄下執行命令mm -B時報錯: ./prebuilts/sdk/tools/jack-admin: line 37:SETTING_VERSION: unbound varia

關於變數關閉的情況,Oracle是如何工作的?

關於如果繫結變數窺探被關閉了,oracle 會怎麼處理的呢?是每次都硬解析還是這樣處理? 首先介紹下繫結變數窺探: 使用SQL首次執行時的值來生成執行計劃。後續再次執行該SQL語句則使用首次執行計劃來執行。 測試版本:Oracle 12.1.0.2

oracle筆記--case的使用和變數

oracle裡的case功能非常強大, 簡單的用法: select  CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END from student; 還沒有當做預處理去使用 select

ORACLE 變數用法總結

之前對ORACLE中的變數一直沒個太清楚的認識,比如說使用:、&、&&、DEIFINE、VARIABLE……等等。今天正好閒下來,上網搜了搜相關的文章,彙總了一下,貼在這裡,方便學習。 ================================

oracle開發過程中儘量使用變數

在儲存過程或者java程式使用sql的過程中,儘量使用繫結變數。否則硬解析太多,比較拖效能。 下面查詢只是空格多了幾個。 SQL> select * from ml_1234 where a

動態建立一組按鈕,併為其變數引數事件方法

做專案時,遇到一個比較奇怪的需求,需要用highChart作圖,但是由於橫座標是公司的部分職級的人員,且人員數目較多,這樣就會造成作出來的圖好長, 在有限的螢幕上顯示不全。於是客戶要求,可以將所有人員根

phpcms手機門戶二開實現任意欄目和定義模板

用phpcms的自帶的手機站模組開發手機站,你可能碰到這樣那樣的問題,比如一下: (1)phpcms手機站無法繫結單頁面 (2)seo無法呼叫關鍵詞或者網站欄目 (3)繫結欄目雖然有排序卻不起作用 (4)如果只繫結父欄目卻無法呼叫列表,還得必須繫結子欄目 (5)欄目