且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[20150706]11G谓词推入问题.txt

更新时间:2022-09-13 11:03:20

[20150706]11G谓词推入问题.txt

--生产系统遇到一个sql语句的问题.
--生产系统的sql语句比较复杂,做一个简化的例子来说明问题.来说明自己优化遇到的困惑。

1.建立测试环境:

SCOTT@test> @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 t1 as select rownum id1, trunc(rownum/10)+1 id2,cast('t1test' as varchar2(20)) pad1 from xmltable('1 to 100000');
create table t2 as select lpad(rownum,10,'0') id1, cast('t2test' as varchar2(20)) pad2 from xmltable('1 to 100000');
create table t3 as select rownum id1, trunc(dbms_random.value(0,100)) x1,trunc(dbms_random.value(0,200)) x2,cast('t3test' as varchar2(20)) pad3 from xmltable('1 to 100000');
create table t4 as select * from t3 where 1=2;
--t4是空表,主要目的这样与生产系统信息符合.没有什么其它意思.
--另外T2表字段id1是字符型的,问题主要在这里。

create unique index pk_t1 on t1 (ID1);
alter table t1 add constraint pk_t1 primary key (id1);
create index i_t1_id2 on t1 (ID2);

create index pk_t2 on t2 (to_number(ID1));
create index i_t3_id1 on t3 (ID1);
create index i_t4_id1 on t4 (ID1);

--分析表忽略.Method_Opt => 'FOR ALL COLUMNS SIZE 1 '

create view v_t3t4  as select * from t3 union all select * from t4;

create or replace view v_tall as
select t1.id1,t1.id2,t1.pad1,t2.pad2,sum_x1,sum_x2
from t1,t2,
(select id1,sum(x1) sum_x1,sum(x2) sum_x2 from v_t3t4 group by id1) vx
where t1.id1=to_number(t2.id1) and t1.id1=vx.id1;


2.因为我的测试环境遇到cardinality feedback问题:
--参考http://blog.itpub.net/267265/viewspace-1724262/
--我在session关闭cardinality feedback。

SCOTT@test> alter session set "_optimizer_use_feedback"=false ;
Session altered.

SCOTT@test> select * from v_tall where id2=42;

SCOTT@test> @dpc '' outline
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  09qkq6x7ju4x2, child number 0
-------------------------------------
select * from v_tall where id2=42
Plan hash value: 431511531
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |      1 |        |       |    53 (100)|          |     10 |00:00:00.01 |      37 |       |       |          |
|   1 |  HASH GROUP BY                  |          |      1 |     10 |   700 |    53   (2)| 00:00:01 |     10 |00:00:00.01 |      37 |   766K|   766K| 1218K (0)|
|   2 |   NESTED LOOPS                  |          |      1 |     10 |   700 |    52   (0)| 00:00:01 |     10 |00:00:00.01 |      37 |       |       |          |
|   3 |    NESTED LOOPS                 |          |      1 |     10 |   390 |    22   (0)| 00:00:01 |     10 |00:00:00.01 |      12 |       |       |          |
|   4 |     TABLE ACCESS BY INDEX ROWID | T1       |      1 |     10 |   160 |     2   (0)| 00:00:01 |     10 |00:00:00.01 |       3 |       |       |          |
|*  5 |      INDEX RANGE SCAN           | I_T1_ID2 |      1 |     10 |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       2 |       |       |          |
|   6 |     TABLE ACCESS BY INDEX ROWID | T2       |     10 |      1 |    23 |     2   (0)| 00:00:01 |     10 |00:00:00.01 |       9 |       |       |          |
|*  7 |      INDEX RANGE SCAN           | PK_T2    |     10 |      1 |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       8 |       |       |          |
|   8 |    VIEW                         | V_T3T4   |     10 |      1 |    31 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |      25 |       |       |          |
|   9 |     UNION ALL PUSHED PREDICATE  |          |     10 |        |       |            |          |     10 |00:00:00.01 |      25 |       |       |          |
|  10 |      TABLE ACCESS BY INDEX ROWID| T3       |     10 |      1 |    12 |     2   (0)| 00:00:01 |     10 |00:00:00.01 |      25 |       |       |          |
|* 11 |       INDEX RANGE SCAN          | I_T3_ID1 |     10 |      1 |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |      15 |       |       |          |
|  12 |      TABLE ACCESS BY INDEX ROWID| T4       |     10 |      1 |    39 |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |       |       |          |
|* 13 |       INDEX RANGE SCAN          | I_T4_ID1 |      0 |      1 |       |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |       |       |          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$25E2CB83
   4 - SEL$25E2CB83 / T1@SEL$2
   5 - SEL$25E2CB83 / T1@SEL$2
   6 - SEL$25E2CB83 / T2@SEL$2
   7 - SEL$25E2CB83 / T2@SEL$2
   8 - SET$5715CE2E / V_T3T4@SEL$3
   9 - SET$5715CE2E
  10 - SEL$8E13D68A / T3@SEL$4
  11 - SEL$8E13D68A / T3@SEL$4
  12 - SEL$9384AC1D / T4@SEL$5
  13 - SEL$9384AC1D / T4@SEL$5

Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      OPT_PARAM('_optimizer_use_feedback' 'false')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$8E13D68A")
      OUTLINE_LEAF(@"SEL$9384AC1D")
      OUTLINE_LEAF(@"SET$5715CE2E")
      PUSH_PRED(@"SEL$25E2CB83" "V_T3T4"@"SEL$3" 3)
      OUTLINE_LEAF(@"SEL$25E2CB83")
      MERGE(@"SEL$3")
      OUTLINE(@"SEL$4")
      OUTLINE(@"SEL$5")
      OUTLINE(@"SET$1")
      OUTLINE(@"SEL$25E2CB83")
      MERGE(@"SEL$3")
      OUTLINE(@"SEL$F5BB74E1")
      MERGE(@"SEL$2")
      OUTLINE(@"SEL$3")
      OUTLINE(@"SEL$1")
      OUTLINE(@"SEL$2")
      INDEX_RS_ASC(@"SEL$25E2CB83" "T1"@"SEL$2" ("T1"."ID2"))
      INDEX_RS_ASC(@"SEL$25E2CB83" "T2"@"SEL$2" "PK_T2")
      NO_ACCESS(@"SEL$25E2CB83" "V_T3T4"@"SEL$3")
      LEADING(@"SEL$25E2CB83" "T1"@"SEL$2" "T2"@"SEL$2" "V_T3T4"@"SEL$3")
      USE_NL(@"SEL$25E2CB83" "T2"@"SEL$2")
      USE_NL(@"SEL$25E2CB83" "V_T3T4"@"SEL$3")
      USE_HASH_AGGREGATION(@"SEL$25E2CB83")
      INDEX_RS_ASC(@"SEL$9384AC1D" "T4"@"SEL$5" ("T4"."ID1"))
      INDEX_RS_ASC(@"SEL$8E13D68A" "T3"@"SEL$4" ("T3"."ID1"))
      END_OUTLINE_DATA
  */

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

   5 - access("T1"."ID2"=42)
   7 - access("T1"."ID1"="T2"."SYS_NC00003$")
  11 - access("ID1"="T1"."ID1")
  13 - access("ID1"="T1"."ID1")
--使用谓词推入。 PUSH_PRED(@"SEL$25E2CB83" "V_T3T4"@"SEL$3" 3)

3.但是如果定义成:
create or replace view v_tallx as
select t1.id1,t1.id2,t1.pad1,t2.pad2,sum_x1,sum_x2,(select dname from dept where deptno=t1.id1) dname
from t1,t2,
(select id1,sum(x1) sum_x1,sum(x2) sum_x2 from v_t3t4 group by id1) vx
where t1.id1=to_number(t2.id1) and t1.id1=vx.id1;

--也就是我加入一个标量子查询,问题出现:

select * from v_tallx where id2=2;

SCOTT@test> @dpc '' outline
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  8j6fp0bc8d9xd, child number 0
-------------------------------------
select * from v_tallx where id2=2

Plan hash value: 1993492796

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name     | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |      1 |        |       |       |   976 (100)|          |     10 |00:00:01.47 |     341 |       |       |          |
|   1 |  TABLE ACCESS BY INDEX ROWID   | DEPT     |     10 |      1 |    13 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       5 |       |       |          |
|*  2 |   INDEX UNIQUE SCAN            | PK_DEPT  |     10 |      1 |       |       |     0   (0)|          |      1 |00:00:00.01 |       4 |       |       |          |
|   3 |  NESTED LOOPS                  |          |      1 |     10 |   590 |       |   976   (1)| 00:00:01 |     10 |00:00:01.47 |     341 |       |       |          |
|   4 |   MERGE JOIN                   |          |      1 |     10 |   470 |       |   956   (1)| 00:00:01 |     10 |00:00:01.47 |     330 |       |       |          |
|   5 |    SORT JOIN                   |          |      1 |    100K|  3027K|       |   953   (1)| 00:00:01 |     20 |00:00:01.47 |     327 |  3667K|   828K| 3259K (0)|
|   6 |     VIEW                       |          |      1 |    100K|  3027K|       |   953   (1)| 00:00:01 |    100K|00:00:01.16 |     327 |       |       |          |
|   7 |      HASH GROUP BY             |          |      1 |    100K|  3027K|  4336K|   953   (1)| 00:00:01 |    100K|00:00:00.96 |     327 |  8785K|  2233K| 9825K (0)|
|   8 |       VIEW                     | V_T3T4   |      1 |    100K|  3027K|       |    96   (2)| 00:00:01 |    100K|00:00:00.69 |     327 |       |       |          |                                                                                              [0/29437]
|   9 |        UNION-ALL               |          |      1 |        |       |       |            |          |    100K|00:00:00.49 |     327 |       |       |          |
|  10 |         TABLE ACCESS FULL      | T3       |      1 |    100K|  1171K|       |    94   (2)| 00:00:01 |    100K|00:00:00.10 |     327 |       |       |          |
|  11 |         TABLE ACCESS FULL      | T4       |      1 |      1 |    39 |       |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |       |       |          |
|* 12 |    SORT JOIN                   |          |     20 |     10 |   160 |       |     3  (34)| 00:00:01 |     10 |00:00:00.01 |       3 |  2048 |  2048 | 2048  (0)|
|  13 |     TABLE ACCESS BY INDEX ROWID| T1       |      1 |     10 |   160 |       |     2   (0)| 00:00:01 |     10 |00:00:00.01 |       3 |       |       |          |
|* 14 |      INDEX RANGE SCAN          | I_T1_ID2 |      1 |     10 |       |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       2 |       |       |          |
|  15 |   TABLE ACCESS BY INDEX ROWID  | T2       |     10 |      1 |    12 |       |     2   (0)| 00:00:01 |     10 |00:00:00.01 |      11 |       |       |          |
|* 16 |    INDEX RANGE SCAN            | PK_T2    |     10 |      1 |       |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       9 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

   1 - SEL$3        / DEPT@SEL$3
   2 - SEL$3        / DEPT@SEL$3
   3 - SEL$F5BB74E1
   6 - SEL$4        / VX@SEL$2
   7 - SEL$4
   8 - SET$1        / V_T3T4@SEL$4
   9 - SET$1
  10 - SEL$5        / T3@SEL$5
  11 - SEL$6        / T4@SEL$6
  13 - SEL$F5BB74E1 / T1@SEL$2
  14 - SEL$F5BB74E1 / T1@SEL$2
  15 - SEL$F5BB74E1 / T2@SEL$2
  16 - SEL$F5BB74E1 / T2@SEL$2

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

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      OPT_PARAM('_optimizer_use_feedback' 'false')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$3")
      OUTLINE_LEAF(@"SEL$5")
      OUTLINE_LEAF(@"SEL$6")
      OUTLINE_LEAF(@"SET$1")
      OUTLINE_LEAF(@"SEL$4")
      OUTLINE_LEAF(@"SEL$F5BB74E1")
      MERGE(@"SEL$2")
      OUTLINE(@"SEL$1")
      OUTLINE(@"SEL$2")
      NO_ACCESS(@"SEL$F5BB74E1" "VX"@"SEL$2")
      INDEX_RS_ASC(@"SEL$F5BB74E1" "T1"@"SEL$2" ("T1"."ID2"))
      INDEX_RS_ASC(@"SEL$F5BB74E1" "T2"@"SEL$2" "PK_T2")
      LEADING(@"SEL$F5BB74E1" "VX"@"SEL$2" "T1"@"SEL$2" "T2"@"SEL$2")
      USE_MERGE(@"SEL$F5BB74E1" "T1"@"SEL$2")
      USE_NL(@"SEL$F5BB74E1" "T2"@"SEL$2")
      NO_ACCESS(@"SEL$4" "V_T3T4"@"SEL$4")
      USE_HASH_AGGREGATION(@"SEL$4")
      FULL(@"SEL$6" "T4"@"SEL$6")
      FULL(@"SEL$5" "T3"@"SEL$5")
      INDEX_RS_ASC(@"SEL$3" "DEPT"@"SEL$3" ("DEPT"."DEPTNO"))
      END_OUTLINE_DATA
  */

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

   2 - access("DEPTNO"=:B1)
  12 - access("T1"."ID1"="VX"."ID1")
       filter("T1"."ID1"="VX"."ID1")
  14 - access("T1"."ID2"=2)
  16 - access("T1"."ID1"="T2"."SYS_NC00003$")

--可以发现T3,T4是全表扫描。谓词推入失效!

--如果写成这样:

select (select dname from dept where deptno=a.id1) ,a.* from v_tall a where id2=2;


SCOTT@test> @dpc '' outline
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  bq98puv7ac22y, child number 1
-------------------------------------
select (select dname from dept where deptno=a.id1) ,a.* from v_tall a
where id2=2
Plan hash value: 1993492796
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name     | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |      1 |        |       |       |   976 (100)|          |     10 |00:00:01.48 |     341 |       |       |          |
|   1 |  TABLE ACCESS BY INDEX ROWID   | DEPT     |     10 |      1 |    13 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       5 |       |       |          |
|*  2 |   INDEX UNIQUE SCAN            | PK_DEPT  |     10 |      1 |       |       |     0   (0)|          |      1 |00:00:00.01 |       4 |       |       |          |
|   3 |  NESTED LOOPS                  |          |      1 |     10 |   590 |       |   976   (1)| 00:00:01 |     10 |00:00:01.48 |     341 |       |       |          |
|   4 |   MERGE JOIN                   |          |      1 |     10 |   470 |       |   956   (1)| 00:00:01 |     10 |00:00:01.48 |     330 |       |       |          |
|   5 |    SORT JOIN                   |          |      1 |    100K|  3027K|       |   953   (1)| 00:00:01 |     20 |00:00:01.48 |     327 |  3667K|   828K| 3259K (0)|
|   6 |     VIEW                       |          |      1 |    100K|  3027K|       |   953   (1)| 00:00:01 |    100K|00:00:01.16 |     327 |       |       |          |
|   7 |      HASH GROUP BY             |          |      1 |    100K|  3027K|  4336K|   953   (1)| 00:00:01 |    100K|00:00:00.96 |     327 |  8785K|  2233K| 9809K (0)|
|   8 |       VIEW                     | V_T3T4   |      1 |    100K|  3027K|       |    96   (2)| 00:00:01 |    100K|00:00:00.69 |     327 |       |       |          |                                                                                              [0/27892]
|   9 |        UNION-ALL               |          |      1 |        |       |       |            |          |    100K|00:00:00.49 |     327 |       |       |          |
|  10 |         TABLE ACCESS FULL      | T3       |      1 |    100K|  1171K|       |    94   (2)| 00:00:01 |    100K|00:00:00.10 |     327 |       |       |          |
|  11 |         TABLE ACCESS FULL      | T4       |      1 |      1 |    39 |       |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |       |       |          |
|* 12 |    SORT JOIN                   |          |     20 |     10 |   160 |       |     3  (34)| 00:00:01 |     10 |00:00:00.01 |       3 |  2048 |  2048 | 2048  (0)|
|  13 |     TABLE ACCESS BY INDEX ROWID| T1       |      1 |     10 |   160 |       |     2   (0)| 00:00:01 |     10 |00:00:00.01 |       3 |       |       |          |
|* 14 |      INDEX RANGE SCAN          | I_T1_ID2 |      1 |     10 |       |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       2 |       |       |          |
|  15 |   TABLE ACCESS BY INDEX ROWID  | T2       |     10 |      1 |    12 |       |     2   (0)| 00:00:01 |     10 |00:00:00.01 |      11 |       |       |          |
|* 16 |    INDEX RANGE SCAN            | PK_T2    |     10 |      1 |       |       |     1   (0)| 00:00:01 |     10 |00:00:00.01 |       9 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

   1 - SEL$2        / DEPT@SEL$2
   2 - SEL$2        / DEPT@SEL$2
   3 - SEL$8976F1A6
   6 - SEL$4        / VX@SEL$3
   7 - SEL$4
   8 - SET$1        / V_T3T4@SEL$4
   9 - SET$1
  10 - SEL$5        / T3@SEL$5
  11 - SEL$6        / T4@SEL$6
  13 - SEL$8976F1A6 / T1@SEL$3
  14 - SEL$8976F1A6 / T1@SEL$3
  15 - SEL$8976F1A6 / T2@SEL$3
  16 - SEL$8976F1A6 / T2@SEL$3

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

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      OPT_PARAM('_optimizer_use_feedback' 'false')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$2")
      OUTLINE_LEAF(@"SEL$5")
      OUTLINE_LEAF(@"SEL$6")
      OUTLINE_LEAF(@"SET$1")
      OUTLINE_LEAF(@"SEL$4")
      OUTLINE_LEAF(@"SEL$8976F1A6")
      MERGE(@"SEL$3")
      OUTLINE(@"SEL$1")
      OUTLINE(@"SEL$3")
      NO_ACCESS(@"SEL$8976F1A6" "VX"@"SEL$3")
      INDEX_RS_ASC(@"SEL$8976F1A6" "T1"@"SEL$3" ("T1"."ID2"))
      INDEX_RS_ASC(@"SEL$8976F1A6" "T2"@"SEL$3" "PK_T2")
      LEADING(@"SEL$8976F1A6" "VX"@"SEL$3" "T1"@"SEL$3" "T2"@"SEL$3")
      USE_MERGE(@"SEL$8976F1A6" "T1"@"SEL$3")
      USE_NL(@"SEL$8976F1A6" "T2"@"SEL$3")
      NO_ACCESS(@"SEL$4" "V_T3T4"@"SEL$4")
      USE_HASH_AGGREGATION(@"SEL$4")
      FULL(@"SEL$6" "T4"@"SEL$6")
      FULL(@"SEL$5" "T3"@"SEL$5")
      INDEX_RS_ASC(@"SEL$2" "DEPT"@"SEL$2" ("DEPT"."DEPTNO"))
      END_OUTLINE_DATA
  */

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

   2 - access("DEPTNO"=:B1)
  12 - access("T1"."ID1"="VX"."ID1")
       filter("T1"."ID1"="VX"."ID1")
  14 - access("T1"."ID2"=2)
  16 - access("T1"."ID1"="T2"."SYS_NC00003$")

--问题依旧!那位知道如何解决这个问题。