ITPub博客

首页 > 数据库 > Oracle > [20210205]警惕toad下优化直方图相关sql语句.txt

[20210205]警惕toad下优化直方图相关sql语句.txt

原创 Oracle 作者:lfree 时间:2021-02-05 16:33:15 0 删除 编辑

[20210205]警惕toad下优化直方图相关sql语句.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有一点点不同.
--//先演示测试环境遇到的情况:

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

create table t 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.测试:
--//先写sql语句在toad sql编辑窗口:
select /*+ gather_plan_statistics */ * from t where flag=:x;
--//然后选择执行,代入参数'0'.获取sql_id=apjr1ppx7hgjm.

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 |        |       |   435 (100)|          |      1 |00:00:00.01 |    1567 |
|*  1 |  TABLE ACCESS FULL| T    |      1 |  50000 |  5273K|   435   (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.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
  */
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]
 
-//注意看下划线,不知道toad下加入OPT_PARAM('_optim_peek_user_binds' 'false'),导致绑定变量peek无效.
--//E-Rows=50000,也就是一半记录,导致执行计划走全表扫描.

--//即使加入提示改写如下:
select /*+ OPT_PARAM('_optim_peek_user_binds' 'true') gather_plan_statistics */ * from t where flag=:x;
--//一样无效.

3.使用dbms_sqldiag包看执行计划分析:

$ cat 10053x.sql
execute dbms_sqldiag.dump_trace(p_sql_id=>'&1',p_child_number=>&2,p_component=>'Compiler',p_file_id=>'a'||'&&1');

SCOTT@book> @ 10053x ctu9k9j5v97wn 0
PL/SQL procedure successfully completed.

SCOTT@book> @ pp
TRACEFILE
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/book/book/trace/book_ora_57333_actu9k9j5v97wn.trc

--//我才发现这样看到的执行计划可能不是真实的执行计划.
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for T[T]
  Column (#3):
    NewDensity:0.000005, OldDensity:0.000005 BktCnt:100000, PopBktCnt:99999, PopValCnt:1, NDV:2
  Column (#3): FLAG(
    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: 1  Computed: 1.00  Non Adjusted: 1.00
  Access Path: TableScan
    Cost:  434.96  Resp: 434.96  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: 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
...

----- Current SQL Statement for this session (sql_id=2scp7tw6bfvzu) -----
/* SQL Analyze(15,0) */ select /*+ gather_plan_statistics */ * from t where flag=:x
----- PL/SQL Stack -----
----- PL/SQL Call Stack -----
  object      line  object
  handle    number  name
0x7bcb1030       145  package body SYS.DBMS_SQLTUNE_INTERNAL
0x7bcb1030     12098  package body SYS.DBMS_SQLTUNE_INTERNAL
0x7d7830c0      1229  package body SYS.DBMS_SQLDIAG
0x7c1b2e80         1  anonymous block
sql_text_length=84
sql=/* SQL Analyze(15,0) */ select /*+ gather_plan_statistics */ * from t where flag=:x
----- Explain Plan Dump -----
----- Plan Table -----

============
Plan Table
============
-----------------------------------------------+-----------------------------------+
| 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:
----------------------
2 - access("FLAG"=:X)

Content of other_xml column
===========================
  db_version     : 11.2.0.4
  parse_schema   : SCOTT
  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
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T"."FLAG"))
    END_OUTLINE_DATA
  */

--//执行计划对不上.outlined里面没有OPT_PARAM('_optim_peek_user_binds' 'false')
--//另外我尝试在toad下执行@ 10053x ctu9k9j5v97wn 0,看到的情况也是一样的.
--//也就是使用dbms_sqldiag包看执行计划分析也要注意.

4.继续分析:
SCOTT@book> alter session set "_optim_peek_user_binds"=false;
Session altered.

SCOTT@book> @ 10053x ctu9k9j5v97wn 0
PL/SQL procedure successfully completed.

--//查看转储,
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for T[T]
  Column (#3):
    NewDensity:0.000005, OldDensity:0.000005 BktCnt:100000, PopBktCnt:99999, PopValCnt:1, NDV:2
  Column (#3): FLAG(
    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
  Access Path: TableScan
    Cost:  434.96  Resp: 434.96  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  --//ix_sel: 0.500000,走索引肯定很差
    Cost: 873.70  Resp: 873.70  Degree: 1
  Best:: AccessPath: TableScan
         Cost: 434.96  Degree: 1  Resp: 434.96  Card: 50000.00  Bytes: 0

    check parallelism for statement[<unnamed>]
kkfdtParallel: parallel is possible (no statement type restrictions)
    kkfdPaForcePrm: dop:1 ()
kkfdPaPrm: use dictionary DOP(1) on table
kkfdPaPrm:- The table : 96021
kkfdPaPrm:DOP = 1 (computed from hint/dictionary/autodop)
kkfdiPaPrm: dop:1 serial(?)
***************************************
...

sql_text_length=84
sql=/* SQL Analyze(44,0) */ select /*+ gather_plan_statistics */ * from t where flag=:x
----- Explain Plan Dump -----
----- Plan Table -----

============
Plan Table
============
-------------------------------------+-----------------------------------+
| Id  | Operation          | Name    | Rows  | Bytes | Cost  | Time      |
-------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT   |         |       |       |   435 |           |
| 1   |  TABLE ACCESS FULL | T       |   49K | 5273K |   435 |  00:00:06 |
-------------------------------------+-----------------------------------+
Predicate Information:
----------------------
1 - filter("FLAG"=:X)

Content of other_xml column
===========================
  db_version     : 11.2.0.4
  parse_schema   : SCOTT
  plan_hash      : 1601196873
  plan_hash_2    : 2498539100
  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
  */

--//设置环境一致后,看到的执行计划一致,实际上dbms_sqldiag包是分析语句
sql=/* SQL Analyze(15,0) */ select /*+ gather_plan_statistics */ * from t where flag=:x
--//不知道为什么toad在执行sql语句时遇到直方图情况是自动加上了OPT_PARAM('_optim_peek_user_binds' 'false').

5.总结:
--//toad 12下要注意这个细节,不然可能遇到无法解析的情况.
--//结果导致加入BIND_AWARE提示无效.
--//另外在11.2.0.3下我看到的情况更加奇怪另外写一篇blog分析.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2756382/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969436