关于or展开的一个bug

描述



近日一个同事发来一个性能极差的sql的10053 trace,据同事说自动收集统计信息是打开的,每天表的数据量变化也不大,说明基本可以排除统计信息不准的情况,最后通过10053发现了一些奇怪的现象,请容我慢慢道来。


问题分析

sql文本


  1. select *
  2.   from (select row_.*, rownum rownum_
  3.           from (SELECT B.KFGZDBH AS PARAM1,
  4.                        ( SELECT MAX(D.GJSJ)
  5.                           FROM FW_DHSQ D
  6.                          WHERE C.KHSQBS = D.KHSQBS) AS PARAM2,
  7.                        A.DDXCSJ AS PARAM3,
  8.                        A.YDQY AS PARAM4,
  9.                        A.XCCLR AS PARAM5,
  10.                        A.GZDZ AS PARAM6,
  11.                        A.KFGZDBS AS PARAM7
  12.                   FROM FW_KFGDXX B, FW_KHSQ C, FW_QXYWFJXX A, FW_DHSQ D
  13.                  WHERE B.KHSQBS = C.KHSQBS
  14.                    AND A.KFGZDBS = B.KFGZDBS
  15.                    AND C.KHSQBS = D.KHSQBS
  16.                    AND B.ZFBZ = '0'
  17.                    AND B.YWLBDM IN ('01')
  18.                    AND B.SLZZBM IN
  19.                        (SELECT ZZBM
  20.                           FROM XT_ZZ Z
  21.                          WHERE Z.ZTBZ = '1'
  22.                          START WITH Z.ZZBM = '0609'
  23.                         CONNECT BY Z.SJZZBM = PRIOR Z.ZZBM)
  24.                    AND B.GZDZTDM = '3'
  25.                    AND B.GDSJ >= to_date('2016-01-01','yyyy-mm-dd')
  26.                    AND B.GDSJ <= sysdate
  27.                    AND (((A.DDXCSJ - D.GJSJ) * 24 * 60 > 45 AND A.YDQY = '1') OR
  28.                        ((A.DDXCSJ - D.GJSJ) * 24 * 60 > 90 AND A.YDQY = '2') OR
  29.                        ((A.DDXCSJ - D.GJSJ) * 24 * 60 > 120 AND A.YDQY = '3'))
  30.                    AND A.DDXCSJ IS NOT NULL
  31.                    AND D.GJSJ IS NOT NULL) row_
  32.          where rownum <= 10)
  33.  where rownum_ > 0

执行计划

============
Plan Table
============
------------------------------------------------------------------------+-----------------------------------+---------------+
| Id  | Operation                                   | Name              | Rows  | Bytes | Cost  | Time      | Pstart| Pstop |
------------------------------------------------------------------------+-----------------------------------+---------------+
| 0   | SELECT STATEMENT                            |                   |       |       |   608 |           |       |       |
| 1   |  SORT AGGREGATE                             |                   |     1 |    25 |       |           |       |       |
| 2   |   TABLE ACCESS BY GLOBAL INDEX ROWID        | FW_DHSQ           |     1 |    25 |     4 |  00:00:01 | ROW LOCATION| ROW LOCATION|
| 3   |    INDEX RANGE SCAN                         | IDX_FW_DHSQ_KHSQBS|     1 |       |     3 |  00:00:01 |       |       |
| 4   |  VIEW                                       |                   |     3 |   477 |   608 |  00:00:08 |       |       |
| 5   |   COUNT STOPKEY                             |                   |       |       |       |           |       |       |
| 6   |    CONCATENATION                            |                   |       |       |       |           |       |       |
| 7   |     FILTER                                  |                   |       |       |       |           |       |       |
| 8   |      FILTER                                 |                   |       |       |       |           |       |       |
| 9   |       NESTED LOOPS SEMI                     |                   |     1 |   193 |   247 |  00:00:03 |       |       |
| 10  |        NESTED LOOPS                         |                   |     1 |   183 |   239 |  00:00:03 |       |       |
| 11  |         NESTED LOOPS                        |                   |     1 |   168 |   238 |  00:00:03 |       |       |
| 12  |          NESTED LOOPS                       |                   |     1 |    87 |   236 |  00:00:03 |       |       |
| 13  |           PARTITION LIST ALL                |                   |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 14  |            TABLE ACCESS FULL                | FW_DHSQ           |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 15  |           TABLE ACCESS FULL                 | FW_QXYWFJXX       |    62 |  3844 |   118 |  00:00:02 |       |       |
| 16  |          TABLE ACCESS BY GLOBAL INDEX ROWID | FW_KFGDXX         |     1 |    81 |     2 |  00:00:01 | ROW LOCATION| ROW LOCATION|
| 17  |           INDEX UNIQUE SCAN                 | PK_FW_KFGDXX      |     1 |       |     1 |  00:00:01 |       |       |
| 18  |         INDEX UNIQUE SCAN                   | PK_FW_KHSQ        |     1 |    15 |     1 |  00:00:01 |       |       |
| 19  |        VIEW                                 | VW_NSO_1          |     1 |    10 |     8 |  00:00:01 |       |       |
| 20  |         FILTER                              |                   |       |       |       |           |       |       |
| 21  |          CONNECT BY WITH FILTERING          |                   |       |       |       |           |       |       |
| 22  |           TABLE ACCESS BY INDEX ROWID       | XT_ZZ             |     1 |    20 |     2 |  00:00:01 |       |       |
| 23  |            INDEX UNIQUE SCAN                | PK_XT_ZZ          |     1 |       |     1 |  00:00:01 |       |       |
| 24  |           NESTED LOOPS                      |                   |     3 |    96 |     6 |  00:00:01 |       |       |
| 25  |            CONNECT BY PUMP                  |                   |       |       |       |           |       |       |
| 26  |            TABLE ACCESS BY INDEX ROWID      | XT_ZZ             |     3 |    60 |     4 |  00:00:01 |       |       |
| 27  |             INDEX RANGE SCAN                | IDX_XT_ZZ_SJZZBM  |     3 |       |     1 |  00:00:01 |       |       |
| 28  |     FILTER                                  |                   |       |       |       |           |       |       |
| 29  |      FILTER                                 |                   |       |       |       |           |       |       |
| 30  |       NESTED LOOPS SEMI                     |                   |     1 |   193 |   217 |  00:00:03 |       |       |
| 31  |        NESTED LOOPS                         |                   |     1 |   183 |   209 |  00:00:03 |       |       |
| 32  |         NESTED LOOPS                        |                   |     1 |   168 |   208 |  00:00:03 |       |       |
| 33  |          NESTED LOOPS                       |                   |     1 |    87 |   206 |  00:00:03 |       |       |
| 34  |           PARTITION LIST ALL                |                   |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 35  |            TABLE ACCESS FULL                | FW_DHSQ           |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 36  |           TABLE ACCESS FULL                 | FW_QXYWFJXX       |    62 |  3844 |    88 |  00:00:02 |       |       |
| 37  |          TABLE ACCESS BY GLOBAL INDEX ROWID | FW_KFGDXX         |     1 |    81 |     2 |  00:00:01 | ROW LOCATION| ROW LOCATION|
| 38  |           INDEX UNIQUE SCAN                 | PK_FW_KFGDXX      |     1 |       |     1 |  00:00:01 |       |       |
| 39  |         INDEX UNIQUE SCAN                   | PK_FW_KHSQ        |     1 |    15 |     1 |  00:00:01 |       |       |
| 40  |        VIEW                                 | VW_NSO_1          |     1 |    10 |     8 |  00:00:01 |       |       |
| 41  |         FILTER                              |                   |       |       |       |           |       |       |
| 42  |          CONNECT BY WITH FILTERING          |                   |       |       |       |           |       |       |
| 43  |           TABLE ACCESS BY INDEX ROWID       | XT_ZZ             |     1 |    20 |     2 |  00:00:01 |       |       |
| 44  |            INDEX UNIQUE SCAN                | PK_XT_ZZ          |     1 |       |     1 |  00:00:01 |       |       |
| 45  |           NESTED LOOPS                      |                   |     3 |    96 |     6 |  00:00:01 |       |       |
| 46  |            CONNECT BY PUMP                  |                   |       |       |       |           |       |       |
| 47  |            TABLE ACCESS BY INDEX ROWID      | XT_ZZ             |     3 |    60 |     4 |  00:00:01 |       |       |
| 48  |             INDEX RANGE SCAN                | IDX_XT_ZZ_SJZZBM  |     3 |       |     1 |  00:00:01 |       |       |
| 49  |     FILTER                                  |                   |       |       |       |           |       |       |
| 50  |      FILTER                                 |                   |       |       |       |           |       |       |
| 51  |       NESTED LOOPS SEMI                     |                   |     1 |   193 |   143 |  00:00:02 |       |       |
| 52  |        NESTED LOOPS                         |                   |     1 |   183 |   135 |  00:00:02 |       |       |
| 53  |         NESTED LOOPS                        |                   |     1 |   168 |   134 |  00:00:02 |       |       |
| 54  |          NESTED LOOPS                       |                   |     1 |    87 |   132 |  00:00:02 |       |       |
| 55  |           PARTITION LIST ALL                |                   |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 56  |            TABLE ACCESS FULL                | FW_DHSQ           |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 57  |           TABLE ACCESS FULL                 | FW_QXYWFJXX       |    62 |  3844 |    14 |  00:00:01 |       |       |
| 58  |          TABLE ACCESS BY GLOBAL INDEX ROWID | FW_KFGDXX         |     1 |    81 |     2 |  00:00:01 | ROW LOCATION| ROW LOCATION|
| 59  |           INDEX UNIQUE SCAN                 | PK_FW_KFGDXX      |     1 |       |     1 |  00:00:01 |       |       |
| 60  |         INDEX UNIQUE SCAN                   | PK_FW_KHSQ        |     1 |    15 |     1 |  00:00:01 |       |       |
| 61  |        VIEW                                 | VW_NSO_1          |     1 |    10 |     8 |  00:00:01 |       |       |
| 62  |         FILTER                              |                   |       |       |       |           |       |       |
| 63  |          CONNECT BY WITH FILTERING          |                   |       |       |       |           |       |       |
| 64  |           TABLE ACCESS BY INDEX ROWID       | XT_ZZ             |     1 |    20 |     2 |  00:00:01 |       |       |
| 65  |            INDEX UNIQUE SCAN                | PK_XT_ZZ          |     1 |       |     1 |  00:00:01 |       |       |
| 66  |           NESTED LOOPS                      |                   |     3 |    96 |     6 |  00:00:01 |       |       |
| 67  |            CONNECT BY PUMP                  |                   |       |       |       |           |       |       |
| 68  |            TABLE ACCESS BY INDEX ROWID      | XT_ZZ             |     3 |    60 |     4 |  00:00:01 |       |       |
| 69  |             INDEX RANGE SCAN                | IDX_XT_ZZ_SJZZBM  |     3 |       |     1 |  00:00:01 |       |       |
------------------------------------------------------------------------+-----------------------------------+---------------+
Predicate Information:
----------------------
3 - access("D"."KHSQBS"=:B1)
4 - filter("ROWNUM_">0)
5 - filter(ROWNUM<=10)
7 - filter(ROWNUM<=10)
8 - filter(TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')<=SYSDATE@!)
14 - filter("D"."GJSJ" IS NOT NULL)
15 - filter(("A"."YDQY"='3' AND "A"."DDXCSJ" IS NOT NULL AND ("A"."DDXCSJ"-"D"."GJSJ")*24*60>120))
16 - filter(("B"."YWLBDM"='01' AND "B"."GZDZTDM"='3' AND "B"."ZFBZ"='0' AND "B"."GDSJ">=TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "B"."GDSJ"<=SYSDATE@!))
17 - access("A"."KFGZDBS"="B"."KFGZDBS")
18 - access("C"."KHSQBS"="D"."KHSQBS")
18 - filter("B"."KHSQBS"="C"."KHSQBS")
19 - filter("B"."SLZZBM"="ZZBM")
20 - filter("Z"."ZTBZ"='1')
21 - access("Z"."SJZZBM"=PRIOR NULL)
23 - access("Z"."ZZBM"='0609')
27 - access("Z"."SJZZBM"="connect$_by$_pump$_009"."PRIOR Z.ZZBM")
28 - filter(ROWNUM<=10)
29 - filter(TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')<=SYSDATE@!)
35 - filter("D"."GJSJ" IS NOT NULL)
36 - filter(("A"."YDQY"='2' AND "A"."DDXCSJ" IS NOT NULL AND ("A"."DDXCSJ"-"D"."GJSJ")*24*60>90 AND (LNNVL("A"."YDQY"='3') OR LNNVL(("A"."DDXCSJ"-"D"."GJSJ")*24*60>120))))
37 - filter(("B"."YWLBDM"='01' AND "B"."GZDZTDM"='3' AND "B"."ZFBZ"='0' AND "B"."GDSJ">=TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "B"."GDSJ"<=SYSDATE@!))
38 - access("A"."KFGZDBS"="B"."KFGZDBS")
39 - access("C"."KHSQBS"="D"."KHSQBS")
39 - filter("B"."KHSQBS"="C"."KHSQBS")
40 - filter("B"."SLZZBM"="ZZBM")
41 - filter("Z"."ZTBZ"='1')
42 - access("Z"."SJZZBM"=PRIOR NULL)
44 - access("Z"."ZZBM"='0609')
48 - access("Z"."SJZZBM"="connect$_by$_pump$_009"."PRIOR Z.ZZBM")
49 - filter(ROWNUM<=10)
50 - filter(TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')<=SYSDATE@!)
56 - filter("D"."GJSJ" IS NOT NULL)
57 - filter(("A"."DDXCSJ" IS NOT NULL AND "A"."YDQY"='1' AND ("A"."DDXCSJ"-"D"."GJSJ")*24*60>45 AND (LNNVL("A"."YDQY"='2') OR LNNVL(("A"."DDXCSJ"-"D"."GJSJ")*24*60>90)) AND (LNNVL("A"."YDQY"='3') OR LNNVL(("A"."DDXCSJ"-"D"."GJSJ")*24*60>120))))
58 - filter(("B"."YWLBDM"='01' AND "B"."GZDZTDM"='3' AND "B"."ZFBZ"='0' AND "B"."GDSJ">=TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "B"."GDSJ"<=SYSDATE@!))
59 - access("A"."KFGZDBS"="B"."KFGZDBS")
60 - access("C"."KHSQBS"="D"."KHSQBS")
60 - filter("B"."KHSQBS"="C"."KHSQBS")
61 - filter("B"."SLZZBM"="ZZBM")
62 - filter("Z"."ZTBZ"='1')
63 - access("Z"."SJZZBM"=PRIOR NULL)
65 - access("Z"."ZZBM"='0609')
69 - access("Z"."SJZZBM"="connect$_by$_pump$_009"."PRIOR Z.ZZBM")

分析执行计划很容易发现CBO对该sql进行了or展开,且每一个or的分支执行计划都几乎一样,所以只需分析一个or的分支即可。
| 9   |       NESTED LOOPS SEMI                     |                   |     1 |   193 |   247 |  00:00:03 |       |       |
| 10  |        NESTED LOOPS                         |                   |     1 |   183 |   239 |  00:00:03 |       |       |
| 11  |         NESTED LOOPS                        |                   |     1 |   168 |   238 |  00:00:03 |       |       |
| 12  |          NESTED LOOPS                       |                   |     1 |    87 |   236 |  00:00:03 |       |       |
| 13  |           PARTITION LIST ALL                |                   |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 14  |            TABLE ACCESS FULL                | FW_DHSQ           |     1 |    25 |   118 |  00:00:02 | 1     | 12    |
| 15  |           TABLE ACCESS FULL                 | FW_QXYWFJXX       |    62 |  3844 |   118 |  00:00:02 |       |       |
| 16  |          TABLE ACCESS BY GLOBAL INDEX ROWID | FW_KFGDXX         |     1 |    81 |     2 |  00:00:01 | ROW LOCATION| ROW LOCATION|
| 17  |           INDEX UNIQUE SCAN                 | PK_FW_KFGDXX      |     1 |       |     1 |  00:00:01 |       |       |
| 18  |         INDEX UNIQUE SCAN                   | PK_FW_KHSQ        |     1 |    15 |     1 |  00:00:01 |       |       |
| 19  |        VIEW                                 | VW_NSO_1          |     1 |    10 |     8 |  00:00:01 |       |       |
| 20  |         FILTER                              |                   |       |       |       |           |       |       |
| 21  |          CONNECT BY WITH FILTERING          |                   |       |       |       |           |       |       |
| 22  |           TABLE ACCESS BY INDEX ROWID       | XT_ZZ             |     1 |    20 |     2 |  00:00:01 |       |       |
| 23  |            INDEX UNIQUE SCAN                | PK_XT_ZZ          |     1 |       |     1 |  00:00:01 |       |       |
| 24  |           NESTED LOOPS                      |                   |     3 |    96 |     6 |  00:00:01 |       |       |
| 25  |            CONNECT BY PUMP                  |                   |       |       |       |           |       |       |
| 26  |            TABLE ACCESS BY INDEX ROWID      | XT_ZZ             |     3 |    60 |     4 |  00:00:01 |       |       |
| 27  |             INDEX RANGE SCAN                | IDX_XT_ZZ_SJZZBM  |     3 |       |     1 |  00:00:01 |       |       |
谓词信息:
14 - filter("D"."GJSJ" IS NOT NULL)
15 - filter(("A"."YDQY"='3' AND "A"."DDXCSJ" IS NOT NULL AND ("A"."DDXCSJ"-"D"."GJSJ")*24*60>120))
16 - filter(("B"."YWLBDM"='01' AND "B"."GZDZTDM"='3' AND "B"."ZFBZ"='0' AND "B"."GDSJ">=TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "B"."GDSJ"<=SYSDATE@!))
先全分区扫描FW_DHSQ表,之后与FW_QXYWFJXX表的连接,连接方式居然是NL(因为连接条件不是等值连接,所以不能进行hash join),且FW_QXYWFJXX表的扫描方式是也是全表扫描,也就是说全表扫描FW_DHSQ表经过谓词过滤后的返回多少记录数就会全表扫描FW_QXYWFJXX多少次。这里初步的判断是FW_DHSQ是一个分区表,但是CBO对FW_DHSQ全分区扫描再经过filter("D"."GJSJ" IS NOT NULL)之后的CARD居然只有1?感觉不太可能。非常可疑。


10053 trace

特别关注了一下optimizer_mode,因为当optimizer_mode为first_row_n时也会出现CARD很小的情况。            
optimizer_mode                      = all_rows
当没有or展开时:
  1. ***************************************
  2. BASE STATISTICAL INFORMATION
  3. ***********************
  4. Table Stats::
  5.   Table: FW_DHSQ Alias: D (Using composite stats) --The '(Using composite stats)' is the notification that the CBO is looking at Global Stats
  6.     #Rows: 587562 #Blks: 16400 AvgRowLen: 146.00 ChainCnt: 0.00
  7. Index Stats::
  8.   Index: IDX_FW_DHSQ_DHHM Col#: 3
  9.     LVLS: 2 #LB: 3177 #DK: 380480 LB/K: 1.00 DB/K: 1.00 CLUF: 569406.00
  10.   Index: IDX_FW_DHSQ_KHSQBS Col#: 2
  11.     LVLS: 2 #LB: 2861 #DK: 587562 LB/K: 1.00 DB/K: 1.00 CLUF: 563875.00
  12.   Index: IDX_FW_DHSQ_YYPTDHBS Col#: 10
  13.     LVLS: 2 #LB: 3164 #DK: 567488 LB/K: 1.00 DB/K: 1.00 CLUF: 563469.00
  14.   Index: PK_FW_DHSQ Col#: 1
  15.     LVLS: 2 #LB: 2772 #DK: 587562 LB/K: 1.00 DB/K: 1.00 CLUF: 563864.00
  16. ***********************

  17. Access path analysis for FW_DHSQ
  18. ***************************************
  19. SINGLE TABLE ACCESS PATH
  20.   Single Table Cardinality Estimation for FW_DHSQ[D]
  21.   Column (#7): GJSJ(
  22.     AvgLen: 8 NDV: 536768 Nulls: 28243 Density: 0.000002 Min: 2457393 Max: 2457542
  23.   Table: FW_DHSQ Alias: D
  24.     Card: Original: 587562.000000 Rounded: 559319 Computed: 559319.00 Non Adjusted: 559319.00
  25.   Access Path: TableScan
  26.     Cost: 4477.31 Resp: 4477.31 Degree: 0
  27.       Cost_io: 4443.00 Cost_cpu: 287184596
  28.       Resp_io: 4443.00 Resp_cpu: 287184596
  29.   ****** trying bitmap/domain indexes ******
  30.   ****** finished trying bitmap/domain indexes ******
  31.   Best:: AccessPath: TableScan
  32.          Cost: 4477.31 Degree: 1 Resp: 4477.31 Card: 559319.00 Bytes: 0      --Card=#Rows-Nulls

  33. ***********************
  34. Join order[20]: FW_DHSQ[D]#2 FW_QXYWFJXX[A]#0 FW_KFGDXX[B]#1 FW_KHSQ[C]#3 VW_NSO_1[VW_NSO_1]#4

  35. ***************
  36. Now joining: FW_QXYWFJXX[A]#0
  37. ***************
  38. NL Join
  39.   Outer table: Card: 559319.00 Cost: 4477.31 Resp: 4477.31 Degree: 1 Bytes: 25
  40. Access path analysis for FW_QXYWFJXX
  41.   Inner table: FW_QXYWFJXX Alias: A
  42.   Access Path: TableScan
  43.     NL Join: Cost: 307647670.59 Resp: 307647670.59 Degree: 1                 --与FW_QXYWFJXX表连接的Cost也很高
  44.       Cost_io: 304180761.00 Cost_cpu: 29017159283431
  45.       Resp_io: 304180761.00 Resp_cpu: 29017159283431
这里CBO的评估都是正确的。

进行or展开之后:
  1. ******** Next OR predicate ********

  2. Trying or-Expansion on query block SEL$93061D6D (#0)

  3. ******** OR-branching ********
  4. ...
  5. Access path analysis for FW_DHSQ
  6. ***************************************
  7. SINGLE TABLE ACCESS PATH
  8.   Single Table Cardinality Estimation for FW_DHSQ[D]
  9.   Column (#7): GJSJ(
  10.     AvgLen: 8 NDV: 536768 Nulls: 28243 Density: 0.000002 Min: 2457393 Max: 2457542
  11.   Table: FW_DHSQ Alias: D
  12.     Card: Original: 15238.000000 Rounded: 1 Computed: 0.00 Non Adjusted: 0.00
  13.   Access Path: TableScan
  14.     Cost: 117.89 Resp: 117.89 Degree: 0
  15.       Cost_io: 117.00 Cost_cpu: 7452753
  16.       Resp_io: 117.00 Resp_cpu: 7452753
  17.   ****** trying bitmap/domain indexes ******
  18.   ****** finished trying bitmap/domain indexes ******
  19.   Best:: AccessPath: TableScan
  20.          Cost: 117.89 Degree: 1 Resp: 117.89 Card: 0.00 Bytes: 0

  21. Access path analysis for FW_DHSQ
  22. ***************************************
  23. SINGLE TABLE ACCESS PATH (First K Rows) --基于rownum的,这里的Card: Original: 15238.000000已经不对了
  24.   Single Table Cardinality Estimation for FW_DHSQ[D]
  25.   Table: FW_DHSQ Alias: D
  26.     Card: Original: 15238.000000 Rounded: 1 Computed: 0.00 Non Adjusted: 0.00
  27.   Access Path: TableScan
  28.     Cost: 117.89 Resp: 117.89 Degree: 0
  29.       Cost_io: 117.00 Cost_cpu: 7452753
  30.       Resp_io: 117.00 Resp_cpu: 7452753
  31.   ****** trying bitmap/domain indexes ******
  32.   ****** finished trying bitmap/domain indexes ******
  33.   Best:: AccessPath: TableScan
  34.          Cost: 117.89 Degree: 1 Resp: 117.89 Card: 0.00 Bytes: 25
Card=0了,难怪会选择这样的执行计划,但是为什么Card=0呢?怀疑和rownum有关。去掉rownum测试


  1. or展开后:
  2. ******** Next OR predicate ********

  3. Trying or-Expansion on query block SEL$93061D6D (#0)

  4. ******** OR-branching ********
  5. ...
  6. ...
  7. Access path analysis for FW_DHSQ
  8. ***************************************
  9. SINGLE TABLE ACCESS PATH
  10.   Single Table Cardinality Estimation for FW_DHSQ[D]
  11.   Column (#7): GJSJ(
  12.     AvgLen: 8 NDV: 552896 Nulls: 29202 Density: 0.000002 Min: 2457393 Max: 2457546
  13.   Table: FW_DHSQ Alias: D
  14.     Card: Original: 606055.000000 Rounded: 576853 Computed: 576853.00 Non Adjusted: 576853.00
  15.   Access Path: TableScan
  16.     Cost: 4768.87 Resp: 4768.87 Degree: 0
  17.       Cost_io: 4733.00 Cost_cpu: 300181750
  18.       Resp_io: 4733.00 Resp_cpu: 300181750
  19.   ****** trying bitmap/domain indexes ******
  20.   ****** finished trying bitmap/domain indexes ******
  21.   Best:: AccessPath: TableScan
  22.          Cost: 4768.87 Degree: 1 Resp: 4768.87 Card: 576853.00 Bytes: 0
CBO评估又正确了。

回头继续分析10053发现:
SVM:     SVM bypassed: ROWNUM column. --Simple View Merging

  1. Final query after transformations:******* UNPARSED QUERY IS *******
  2. SELECT "from$_subquery$_001"."PARAM1" "PARAM1", "from$_subquery$_001"."PARAM2" "PARAM2",
  3.   "from$_subquery$_001"."PARAM3" "PARAM3", "from$_subquery$_001"."PARAM4" "PARAM4",
  4.   "from$_subquery$_001"."PARAM5" "PARAM5", "from$_subquery$_001"."PARAM6" "PARAM6",
  5.   "from$_subquery$_001"."PARAM7" "PARAM7", "from$_subquery$_001"."ROWNUM_" "ROWNUM_"
  6. FROM
  7.   (
  8.     SELECT "B"."KFGZDBH" "PARAM1", (
  9.         SELECT MAX("D"."GJSJ") "MAX(D.GJSJ)"
  10.         FROM "YXSC_ER"."FW_DHSQ" "D"
  11.         WHERE "D"."KHSQBS" = "C"."KHSQBS"
  12.         ) "PARAM2", "A"."DDXCSJ" "PARAM3", "A"."YDQY" "PARAM4",
  13.       "A"."XCCLR" "PARAM5", "A"."GZDZ" "PARAM6", "A"."KFGZDBS" "PARAM7",
  14.       ROWNUM "ROWNUM_"
  15.     FROM
  16.       (
  17.         SELECT "Z"."ZZBM" "ZZBM"
  18.         FROM "YXSC_ER"."XT_ZZ" "Z"
  19.         WHERE "Z"."ZTBZ" = '1'
  20.         START WITH "Z"."ZZBM" = '0609'
  21.         CONNECT BY "Z"."SJZZBM" = PRIOR "Z"."ZZBM"
  22.       )"VW_NSO_1", "YXSC_ER"."FW_KFGDXX" "B", "YXSC_ER"."FW_KHSQ" "C",
  23.       "YXSC_ER"."FW_QXYWFJXX" "A", "YXSC_ER"."FW_DHSQ" "D"
  24.     WHERE ROWNUM<= 10
  25.       AND "B"."KHSQBS" = "C"."KHSQBS"
  26.       AND "A"."KFGZDBS" = "B"."KFGZDBS"
  27.       AND "C"."KHSQBS" = "D"."KHSQBS"
  28.       AND "B"."ZFBZ" = '0'
  29.       AND "B"."YWLBDM" = '01'
  30.       AND "B"."SLZZBM" = "VW_NSO_1"."ZZBM"
  31.       AND "B"."GZDZTDM" = '3'
  32.       AND "B"."GDSJ" >= TO_DATE(' 2016-01-01 00:00:00',
  33.         'syyyy-mm-dd hh24:mi:ss')
  34.       AND "B"."GDSJ" <= SYSDATE@!
  35.       AND (("A"."DDXCSJ" - "D"."GJSJ")* 24 * 60 > 45
  36.         AND "A"."YDQY" = '1'
  37.         OR ("A"."DDXCSJ" - "D"."GJSJ")* 24 * 60 > 90
  38.         AND "A"."YDQY" = '2'
  39.         OR ("A"."DDXCSJ" - "D"."GJSJ")* 24 * 60 > 120
  40.         AND "A"."YDQY" = '3')
  41.       AND "A"."DDXCSJ" IS NOT NULL
  42.       AND "D"."GJSJ" IS NOT NULL
  43.       AND TO_DATE(' 2016-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') <= SYSDATE@!
  44.   )"from$_subquery$_001"
  45. WHERE "from$_subquery$_001"."ROWNUM_" > 0
由于CBO对sql做了 Simple View Merging, rownum和or展开出现在了同一个查询块里。感觉是or展开和rownum出现在同一个查询块时,CBO就会评估错误。

MOS

Bug 15996520 - Suboptimal execution plan OR expansion and First K rows (Doc ID 15996520.8)
If a First K Rows mode query gets a suboptimal query execution plan with OR expansion and full table scans, with low estimated cardinalities and cost then you may have encountered this bug.

Affects:

Product (Component) Oracle Server (Rdbms)
Range of versions believed to be affected (Not specified)
Versions confirmed as being affected
  • 11.2.0.3
Platforms affected Generic (all / most platforms affected)

Fixed:

The fix for 15996520 is first included in
  • 12.2 (Future Release)
  • 12.1.0.2 (Server Patch Set)
  • 11.2.0.4 (Server Patch Set)
  • 11.2.0.3 Patch 16 on Windows Platforms

该数据库正好是11.2.0.3


解决方


  • 1.将数据库版本升到11.2.0.4.
  • 2.不要让rownum和or展开出现在同一个查询块里(该例采用/*+ no_expand*/禁用了or展开).



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

转载于:http://blog.itpub.net/31347199/viewspace-2118035/

你可能感兴趣的:(关于or展开的一个bug)