您的位置:首页 > 其它

错误的转换绑定变量类型导致执行计划错误

2014-03-28 17:47 381 查看
昨天开发来问我个问题,一个业务sql执行缓慢,下面

SQL> SELECT A.ISSUE_OID,

      (SELECT B.ISSUE_END_TIME FROM ISSUE_T B WHERE A.ISSUE_OID = B.IWOID) AS ISSUE_END_TIME,

      (SELECT C.ENCASH_END_TIME FROM ISSUE_T C WHERE A.ISSUE_OID = C.IWOID) AS ENCASH_END_TIME,

      A.OPERATOR_ID,

      ...

 FROM SALE_DETAIL_T A

WHERE 1 = 1

  AND A.TICKET_STATE = ?

  AND A.SALE_TIME between ? and ?

......

SALE_DETAIL_T 数据600w,返回结果少量,SALE_TIME是索引列

带入参数,查看执行计划

----------------------------------------------------------------------------------------------------------

| Id  | Operation                    | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |                           |     1 |   187 |     3  (34)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    41 |     2   (0)| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|   3 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    41 |     2   (0)| 00:00:01 |

|*  4 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|   5 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    37 |     2   (0)| 00:00:01 |

|*  6 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|   7 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    36 |     2   (0)| 00:00:01 |

|*  8 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|   9 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    36 |     2   (0)| 00:00:01 |

|* 10 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|  11 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    37 |     2   (0)| 00:00:01 |

|* 12 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|  13 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    37 |     2   (0)| 00:00:01 |

|* 14 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|  15 |  TABLE ACCESS BY INDEX ROWID | ISSUE_T                   |     1 |    37 |     2   (0)| 00:00:01 |

|* 16 |   INDEX UNIQUE SCAN          | PK_ISSUE_T                |     1 |       |     1   (0)| 00:00:01 |

|  17 |  HASH GROUP BY               |                           |     1 |   187 |     3  (34)| 00:00:01 |

|* 18 |   TABLE ACCESS BY INDEX ROWID| SALE_DETAIL_T             |     1 |   187 |     2   (0)| 00:00:01 |

|* 19 |    INDEX RANGE SCAN          | SALE_DETAIL_SALE_TIME_IDX |     1 |       |     2   (0)| 00:00:01 |

----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("B"."IWOID"=:B1)

   4 - access("C"."IWOID"=:B1)

   6 - access("E"."IWOID"=:B1)

   8 - access("D"."IWOID"=:B1)

  10 - access("E"."IWOID"=:B1)

  12 - access("F"."IWOID"=:B1)

  14 - access("G"."IWOID"=:B1)

  16 - access("H"."IWOID"=:B1)

  18 - filter("A"."TICKET_STATE"=1)

  19 - access("A"."SALE_TIME">=TO_DATE('2014-03-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND

              "A"."SALE_TIME"<=TO_DATE('2014-03-01 23:59:59', 'yyyy-mm-dd hh24:mi:ss'))

       filter(SYS_OP_DESCEND("A"."SALE_TIME")<=HEXTORAW('878DFCFEF8FEF8FF')  AND

              SYS_OP_DESCEND("A"."SALE_TIME")>=HEXTORAW('878DFCFEE7C3C3FF') )

Statistics

----------------------------------------------------------

          1  recursive calls

          0  db block gets

          3  consistent gets

          0  physical reads

          0  redo size

       1419  bytes sent via SQL*Net to client

        457  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          0  rows processed

真实的执行计划如下

---------------------------------------------------------------------------------------------

| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |               |   125 | 23375 |   101K  (2)| 00:20:15 |

|   1 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    41 |     2   (0)| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|   3 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    41 |     2   (0)| 00:00:01 |

|*  4 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|   5 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    37 |     2   (0)| 00:00:01 |

|*  6 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|   7 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    36 |     2   (0)| 00:00:01 |

|*  8 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|   9 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    36 |     2   (0)| 00:00:01 |

|* 10 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|  11 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    37 |     2   (0)| 00:00:01 |

|* 12 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|  13 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    37 |     2   (0)| 00:00:01 |

|* 14 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|  15 |  TABLE ACCESS BY INDEX ROWID| ISSUE_T       |     1 |    37 |     2   (0)| 00:00:01 |

|* 16 |   INDEX UNIQUE SCAN         | PK_ISSUE_T    |     1 |       |     1   (0)| 00:00:01 |

|  17 |  HASH GROUP BY              |               |   125 | 23375 |   101K  (2)| 00:20:15 |

|* 18 |   FILTER                    |               |       |       |            |          |

|* 19 |    TABLE ACCESS FULL        | SALE_DETAIL_T | 15932 |  2909K|   101K  (2)| 00:20:15 |

---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("B"."IWOID"=:B1)

   4 - access("C"."IWOID"=:B1)

   6 - access("E"."IWOID"=:B1)

   8 - access("D"."IWOID"=:B1)

  10 - access("E"."IWOID"=:B1)

  12 - access("F"."IWOID"=:B1)

  14 - access("G"."IWOID"=:B1)

  16 - access("H"."IWOID"=:B1)

  18 - filter(TO_TIMESTAMP('2014-03-01 00:00:00',:B1)<=TO_TIMESTAMP('2014-03-01

              23:59:59',:B2))

  19 - filter(INTERNAL_FUNCTION("A"."SALE_TIME")>=TO_TIMESTAMP('2014-03-01

              00:00:00',:B1) AND INTERNAL_FUNCTION("A"."SALE_TIME")<=TO_TIMESTAMP('2014-03-01

              23:59:59',:B2) AND "A"."TICKET_STATE"=1)

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

     455964  consistent gets

     413600  physical reads

          0  redo size

       1419  bytes sent via SQL*Net to client

        457  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          0  rows processed

可以看到走了全表扫描,排查多种可能(也考虑到绑定变量窥探的情况,过程省略),结果很奇葩,原因是开发提交sql之前对绑定变量的类型使用的是to_timestamp方法,正确的应该用to_date转换争取的类型即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: