[20210205]警惕toad下優化直方圖相關sql語句3.txt

lfree發表於2021-02-07

[20210205]警惕toad下優化直方圖相關sql語句3.txt

--//今天優化sql語句在toad12 ,我發現一個奇怪現象,語句的執行計劃不使用我建立的索引.折騰N久,才想起以前遇到
--//的情況,連結如下:http://blog.itpub.net/267265/viewspace-2668520/=>[20191213]toad 12下BIND_AWARE提示無效.txt
--//問題我優化的資料庫11.2.0.3與我的測試環境11.2.0.4有一點點不同.
--//toad 版本12.6.0.53.
--//本來想那原始語句來分析,設計到一些安全問題,我只能建立例子來分析:

1.環境:
> @ ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.3.0     Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

create table t tablespace users as select rownum id ,lpad('x',100,'x') name ,lpad('1',1) flag from dual connect by level<=1e5;
update t set flag='0' where id=1e5;
commit ;
create index i_t_flag on t(flag);

SCOTT@book> execute sys.dbms_stats.gather_table_stats ( OwnName => '',TabName => 't',Estimate_Percent => NULL,
Method_Opt=> 'FOR ALL COLUMNS SIZE 1 for columns flag size 4',Cascade => True ,No_Invalidate => false)
PL/SQL procedure successfully completed.

2.測試:
--//在toad介面下執行:
show parameter cursor_sharing
cursor_sharing                       string   EXACT
--//排除http://blog.itpub.net/267265/viewspace-2749843/=>[20210114]toad檢視真實執行計劃問題.txt,補充說明我修改了觸發器.
CREATE OR REPLACE TRIGGER SYS.LOGIN_ON_RECORD_IP
   AFTER LOGON
   ON DATABASE
DECLARE
   v_client_info   v$session.client_info%TYPE;
BEGIN
   v_client_info := NVL (SYS_CONTEXT ('userenv', 'ip_address'), '127.0.0.1');
   DBMS_APPLICATION_INFO.set_client_info (v_client_info);
   DBMS_SESSION.set_identifier (v_client_info);

   IF (USER <> 'SYS' and  USER <> 'SYSTEM')
   THEN
      EXECUTE IMMEDIATE 'alter session set cursor_sharing =force';
   END IF;
END;
/

--//先寫sql語句在toad sql編輯視窗:
select /*+ gather_plan_statistics */ * from t where flag=:x;
--//然後選擇執行,代入引數'0'.獲取sql_id=ctu9k9j5v97wn.

SQL_ID  ctu9k9j5v97wn, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ * from t where flag=:x
Plan hash value: 1601196873
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |   436 (100)|          |      1 |00:00:00.01 |    1567 |
|*  1 |  TABLE ACCESS FULL| T    |      1 |  50000 |  5273K|   436   (1)| 00:00:06 |      1 |00:00:00.01 |    1567 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$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")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"=:X)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
   1 - "T"."ID"[NUMBER,22], "T"."NAME"[VARCHAR2,100], "FLAG"[VARCHAR2,1]
--//理論應該選擇我建立的索引,注意看A-Rows=1,選擇索引是最佳選擇,這裡還有一個細節,我發現這樣執行計劃裡面看不到繫結變數值.

> @ bind_cap ctu9k9j5v97wn ''
SQL_ID        CHILD_NUMBER WAS NAME                                       POSITION MAX_LENGTH LAST_CAPTURED       DATATYPE_STRING VALUE_STRING
------------- ------------ --- ---------------------------------------- ---------- ---------- ------------------- --------------- -------------
ctu9k9j5v97wn            0 YES :X                                                1         32 2021-02-05 16:49:41 VARCHAR2(32)    0

--//我不知道為什麼出現這樣的情況,很奇怪的是如果我在測試環境執行版本11.2.0.4,在Outline Data部分看到如下:

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      OPT_PARAM('_optim_peek_user_binds' 'false')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */

3.使用10053分析:
--//我在toad的sql編輯視窗輸入如下,注意sql語句必須做一些改動不然不會硬解析,我修改select為seLECT:
alter session set events '10053 trace name context forever, level 12';
seLECT /*+ gather_plan_statistics */ * from t where flag=:x;
alter session set events '10053 trace name context off';

--//注意要分別別執行.也就是先輸入alter session set events '10053 trace name context forever, level 12';,然後清除,在執行語句.
--//最後alter session set events '10053 trace name context off';.
--//在sqlplus上重複執行以以上步驟.
variable x varchar2(1);
exec :x := '0';
alter session set events '10053 trace name context forever, level 12';
seLECT /*+ gather_plan_statistics */ * from t where flag=:x;
alter session set events '10053 trace name context off';

# diff -Nur hrp430_ora_19023.trc hrp430_ora_19938.trc  > diff.txt
--//檢查不同發現:
....
 
-Registered qb: SEL$1 0xdf0e6678 (PARSER)
+Registered qb: SEL$1 0x44ee6a80 (PARSER)
 ---------------------
 QUERY BLOCK SIGNATURE
 ---------------------
@@ -1158,25 +1158,26 @@
 
 apadrv-start sqlid=7032951094734105818
   :
-    call(in-use=1400, alloc=16344), compile(in-use=56624, alloc=58184), execution(in-use=3544, alloc=4032)
+    call(in-use=1464, alloc=16344), compile(in-use=56560, alloc=58632), execution(in-use=3544, alloc=4032)
 
 *******************************************
 Peeked values of the binds in SQL statement
 *******************************************
 ----- Bind Info (kkscoacd) -----
  Bind#0
-  oacdty=01 mxl=32(02) mxlc=00 mal=00 scl=00 pre=00
-  oacflg=01 fl2=1000010 frm=01 csi=852 siz=32 off=0
-  No bind buffers allocated
+  oacdty=01 mxl=32(01) mxlc=00 mal=00 scl=00 pre=00
+  oacflg=03 fl2=1000000 frm=01 csi=852 siz=32 off=0
+  kxsbbbfp=2ac244f32f88  bln=32  avl=01  flg=05
+  value="0"
--//問題出在這裡嗎?toad下看不到繫結變數值,導致10053分析有誤嗎?

 
 Final query after transformations:******* UNPARSED QUERY IS *******
 SELECT "T"."ID" "ID","T"."NAME" "NAME","T"."FLAG" "FLAG" FROM "SYS"."T" "T" WHERE "T"."FLAG"=:B1
 kkoqbc: optimizing query block SEL$1 (#0)
         
         :
-    call(in-use=1448, alloc=16344), compile(in-use=57552, alloc=58184), execution(in-use=3680, alloc=4032)
+    call(in-use=1512, alloc=16344), compile(in-use=57496, alloc=58632), execution(in-use=3680, alloc=4032)
 
-kkoqbc-subheap (create addr=0x2b85df0ef698)
+kkoqbc-subheap (create addr=0x2ac244eefaa0)
 ****************
 QUERY BLOCK TEXT
 ****************
@@ -1215,18 +1216,19 @@
     AvgLen: 2 NDV: 2 Nulls: 0 Density: 0.000005
     Histogram: Freq  #Bkts: 2  UncompBkts: 100000  EndPtVals: 2
   Table: T  Alias: T
-    Card: Original: 100000.000000  Rounded: 50000  Computed: 50000.00  Non Adjusted: 50000.00
+    Card: Original: 100000.000000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
   Access Path: TableScan
     Cost:  435.68  Resp: 435.68  Degree: 0
       Cost_io: 434.00  Cost_cpu: 35372940
       Resp_io: 434.00  Resp_cpu: 35372940
   Access Path: index (AllEqRange)
     Index: I_T_FLAG
-    resc_io: 873.00  resc_cpu: 25717867
-    ix_sel: 0.500000  ix_sel_with_filters: 0.500000
-    Cost: 874.22  Resp: 874.22  Degree: 1
-  Best:: AccessPath: TableScan
-         Cost: 435.68  Degree: 1  Resp: 435.68  Card: 50000.00  Bytes: 0
+    resc_io: 2.00  resc_cpu: 15483
+    ix_sel: 0.000010  ix_sel_with_filters: 0.000010
+    Cost: 2.00  Resp: 2.00  Degree: 1
+  Best:: AccessPath: IndexRange
+  Index: I_T_FLAG
+         Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0
 
 ***************************************
 
@@ -1239,7 +1241,7 @@
 Permutations for Starting Table :0
 Join order[1]:  T[T]#0
 ***********************
-Best so far:  Table#: 0  cost: 435.6827  card: 50000.0000  bytes: 5400000
+Best so far:  Table#: 0  cost: 2.0007  card: 1.0000  bytes: 108
 ***********************
 (newjo-stop-1) k:0, spcnt:0, perm:1, maxperm:2000
 
@@ -1250,27 +1252,28 @@
 
 Trying or-Expansion on query block SEL$1 (#0)
 Transfer Optimizer annotations for query block SEL$1 (#0)
-id=0 frofand predicate="T"."FLAG"=:B1
+id=0 frofkks[i] (index start key) predicate="T"."FLAG"=:B1
+id=0 frofkke[i] (index stop key) predicate="T"."FLAG"=:B1
 Final cost for query block SEL$1 (#0) - All Rows Plan:
   Best join order: 1
-  Cost: 435.6827  Degree: 1  Card: 50000.0000  Bytes: 5400000
-  Resc: 435.6827  Resc_io: 434.0000  Resc_cpu: 35372940
-  Resp: 435.6827  Resp_io: 434.0000  Resc_cpu: 35372940
-kkoqbc-subheap (delete addr=0x2b85df0ef698, in-use=13600, alloc=16408)
+  Cost: 2.0007  Degree: 1  Card: 1.0000  Bytes: 108
+  Resc: 2.0007  Resc_io: 2.0000  Resc_cpu: 15483
+  Resp: 2.0007  Resp_io: 2.0000  Resc_cpu: 15483
+kkoqbc-subheap (delete addr=0x2ac244eefaa0, in-use=13696, alloc=16408)
 kkoqbc-end:
         :
-    call(in-use=12800, alloc=49184), compile(in-use=58408, alloc=62328), execution(in-use=4048, alloc=8088)
+    call(in-use=12864, alloc=49184), compile(in-use=58744, alloc=59424), execution(in-use=4184, alloc=8088)
 
 kkoqbc: finish optimizing query block SEL$1 (#0)
 apadrv-end
           :
-    call(in-use=12800, alloc=49184), compile(in-use=59320, alloc=62328), execution(in-use=4048, alloc=8088)
+    call(in-use=12864, alloc=49184), compile(in-use=59656, alloc=63568), execution(in-use=4184, alloc=8088)
 
 
 Starting SQL statement dump
 
-user_id=0 user_name=SYS module=TOAD 12.6.0.53 action=
-sql_id=636hgs8q54b6u plan_hash_value=1601196873 problem_type=3
+user_id=0 user_name=SYS module=sqlplus@gxqyydg4 (TNS V1-V3) action=
+sql_id=636hgs8q54b6u plan_hash_value=120143814 problem_type=3
 ----- Current SQL Statement for this session (sql_id=636hgs8q54b6u) -----
 seLECT /*+ gather_plan_statistics */ * from t where flag=:x
 sql_text_length=60
@@ -1281,22 +1284,33 @@
 ============
 Plan Table
 ============
--------------------------------------+-----------------------------------+
-| Id  | Operation          | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
-| 0   | SELECT STATEMENT   |         |       |       |   436 |           |
-| 1   |  TABLE ACCESS FULL | T       |   49K | 5273K |   436 |  00:00:06 |
--------------------------------------+-----------------------------------+
+-----------------------------------------------+-----------------------------------+
+| Id  | Operation                    | Name    | Rows  | Bytes | Cost  | Time      |
+-----------------------------------------------+-----------------------------------+
+| 0   | SELECT STATEMENT             |         |       |       |     2 |           |
+| 1   |  TABLE ACCESS BY INDEX ROWID | T       |     1 |   108 |     2 |  00:00:01 |
+| 2   |   INDEX RANGE SCAN           | I_T_FLAG|     1 |       |     1 |  00:00:01 |
+-----------------------------------------------+-----------------------------------+
 Predicate Information:
 ----------------------
-1 - filter("FLAG"=:X)
+2 - access("FLAG"=:X)
 
 Content of other_xml column
 ===========================
   db_version     : 11.2.0.3
   parse_schema   : SYS
-  plan_hash      : 1601196873
-  plan_hash_2    : 2498539100
+  plan_hash      : 120143814
+  plan_hash_2    : 2969257144
+Peeked Binds
+============
+  Bind variable information
+    position=1
+    datatype(code)=1
+    datatype(string)=VARCHAR2(32)
+    char set id=852
+    char format=1
+    max length=32
+    value=0
   Outline Data:
   /*+
     BEGIN_OUTLINE_DATA
@@ -1305,7 +1319,7 @@
       DB_VERSION('11.2.0.3')
       ALL_ROWS
       OUTLINE_LEAF(@"SEL$1")
-      FULL(@"SEL$1" "T"@"SEL$1")
+      INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T"."FLAG"))
     END_OUTLINE_DATA
   */
 
@@ -2288,13 +2302,13 @@
 
 
 Query Block Registry:
-SEL$1 0xdf0e6678 (PARSER) [FINAL]
+SEL$1 0x44ee6a80 (PARSER) [FINAL]
 
 :
-    call(in-use=15720, alloc=49184), compile(in-use=87608, alloc=149600), execution(in-use=7224, alloc=8088)
+    call(in-use=15832, alloc=49184), compile(in-use=90560, alloc=153784), execution(in-use=9096, alloc=12144)
 
 End of Optimizer State Dump
 Dumping Hints
 =============
-  atom_hint=(@=0xac161720 err=0 resol=0 used=1 token=821 org=1 lvl=1 txt=GATHER_PLAN_STATISTICS ())
+  atom_hint=(@=0xa662f820 err=0 resol=0 used=1 token=821 org=1 lvl=1 txt=GATHER_PLAN_STATISTICS ())
 ====================== END SQL Statement Dump ======================

3.在sqlplus執行:
> select /*+ gather_plan_statistics full(t) */ * from t where flag=:x;
        ID NAME                                     F
---------- ---------------------------------------- -
    100000 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0
           xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
           xxxxxxxxxxxxxxxxxxxx

> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  6q1d1n59rcgjm, child number 0
-------------------------------------
select /*+ gather_plan_statistics full(t) */ * from t where flag=:x
Plan hash value: 1601196873

--------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |   436 (100)|          |      1 |00:00:00.01 |    1567 |
|*  1 |  TABLE ACCESS FULL| T    |      1 |      1 |   108 |   436   (1)| 00:00:06 |      1 |00:00:00.01 |    1567 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
Peeked Binds (identified by position):
--------------------------------------
   1 - (VARCHAR2(30), CSID=852): '0'
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"=:X)
28 rows selected.
--//在sqlplus下即使全表掃描,也能看到Peeked Binds部分.

 SELECT *
    FROM v$sql_plan
   WHERE sql_id IN ('6q1d1n59rcgjm', 'ctu9k9j5v97wn') AND child_number = 0
ORDER BY id;

--//主要不同是other_xml:
6q1d1n59rcgjm <other_xml><info type="db_version">11.2.0.3</info><info type="parse_schema"><![CDATA["SYS"]]></info><info type="plan_hash">1601196873</info><info type="plan_hash_2">2498539100</info><peeked_binds><bind nam=":X" pos="1" dty="1" csi="852" frm="1" mxl="32">30</bind></peeked_binds><outline_data><hint><![CDATA[IGNORE_OPTIM_EMBEDDED_HINTS]]></hint><hint><![CDATA[OPTIMIZER_FEATURES_ENABLE('11.2.0.3')]]></hint><hint><![CDATA[DB_VERSION('11.2.0.3')]]></hint><hint><![CDATA[ALL_ROWS]]></hint><hint><![CDATA[OUTLINE_LEAF(@"SEL$1")]]></hint><hint><![CDATA[FULL(@"SEL$1" "T"@"SEL$1")]]></hint></outline_data></other_xml>
ctu9k9j5v97wn <other_xml><info type="db_version">11.2.0.3</info><info type="parse_schema"><![CDATA["SYS"]]></info><info type="plan_hash">1601196873</info><info type="plan_hash_2">2498539100</info><outline_data><hint><![CDATA[IGNORE_OPTIM_EMBEDDED_HINTS]]></hint><hint><![CDATA[OPTIMIZER_FEATURES_ENABLE('11.2.0.3')]]></hint><hint><![CDATA[DB_VERSION('11.2.0.3')]]></hint><hint><![CDATA[ALL_ROWS]]></hint><hint><![CDATA[OUTLINE_LEAF(@"SEL$1")]]></hint><hint><![CDATA[FULL(@"SEL$1" "T"@"SEL$1")]]></hint></outline_data></other_xml>

<peeked_binds><bind nam=":X" pos="1" dty="1" csi="852" frm="1" mxl="32">30</bind></peeked_binds>

--//很奇怪為什麼toad下生成的執行計劃沒有取得繫結變化值.
--//我發別在sqlplus和toad下執行
> @ share 2kby5rjcxp08g ''
SQL_TEXT                       = select /*+ gather_plan_statistics */ * from t where Flag=:x
SQL_ID                         = 2kby5rjcxp08g
ADDRESS                        = 00000000AD256620
CHILD_ADDRESS                  = 00000000AD2561C0
CHILD_NUMBER                   = 0
REASON                         = <ChildNode><ChildNumber>0</ChildNumber><ID>30</ID><reason>User Bind Peek settings
mismatch(0)</reason><size>8x4</size><ctxflg>1073774864</ctxflg><ctxyfl>6291584</ctxyfl><kksciflg>4122</kksciflg><kkscyfl>6291584</kkscyfl><ctxbposc>65537</ctxbposc><KXSUSB_NEWBND_DRIVER>1</KXSUSB_NEWBND_DRIVER><kxscfl3>2181169216</kxscfl3><_optim_peek_user_binds>1</_optim_peek_us
er_binds></ChildNode>
--------------------------------------------------
SQL_TEXT                       = select /*+ gather_plan_statistics */ * from t where Flag=:x
SQL_ID                         = 2kby5rjcxp08g
ADDRESS                        = 00000000AD256620
CHILD_ADDRESS                  = 00000000A5391878
CHILD_NUMBER                   = 1
USER_BIND_PEEK_MISMATCH        = Y
REASON                         =
--------------------------------------------------
PL/SQL procedure successfully completed.

--//從這裡可以看出一定是_optim_peek_user_binds在作怪.不知道為什麼放棄..

4.繼續測試:
--//sqlplus 下:
alter session set "_optim_peek_user_binds"=false;
variable x varchar2(1);
exec :x := '0';
Select /*+ gather_plan_statistics */ * from t where flag=:x;

> @ dpc '' outline
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  dwt8xfty8qn8a, child number 0
-------------------------------------
Select /*+ gather_plan_statistics */ * from t where flag=:x
Plan hash value: 1601196873
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |   436 (100)|          |      1 |00:00:00.01 |    1567 |
|*  1 |  TABLE ACCESS FULL| T    |      1 |  50000 |  5273K|   436   (1)| 00:00:06 |      1 |00:00:00.01 |    1567 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      OPT_PARAM('_optim_peek_user_binds' 'false')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"=:X)

--//只要設定"_optim_peek_user_binds"=false;,就看不到繫結變數peek的部分資訊.
--//換一句話講只要在toad第一次執行硬分析,不管任何sql語句執行計劃就沒有Peeked Binds 資訊,就是不會做peek.
--//導致存在直方圖有關sql語句解析報錯.很奇怪的是11.2.0.4在outline date存在
OPT_PARAM('_optim_peek_user_binds' 'false')
--//而11.2.0.3就沒有.不知道什麼回事.也許toad下執行sql語句存在什麼特殊之處.
--//也就是提醒自己使用toad優化sql語句要注意這些細節.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-2756573/,如需轉載,請註明出處,否則將追究法律責任。

相關文章