在解释计划中以文字形式显示日期

时间:2018-11-08 10:47:55

标签: sql oracle oracle-sqldeveloper sql-execution-plan

SELECT DISTINCT i.name, i.daily_cost
FROM edu_event.items i
WHERE i.purchase_date BETWEEN DATE'2015-01-01' AND DATE'2015-12-31';

对于此查询,选择了以下执行计划:

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |  5750 |   213K|   206   (1)| 00:00:01 |
|   1 |  HASH UNIQUE       |       |  5750 |   213K|   206   (1)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| ITEMS |  5750 |   213K|   205   (1)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("I"."PURCHASE_DATE">=TO_DATE('2015-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "I"."PURCHASE_DATE"<=TO_DATE('2015-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

如您所见,原始日期文字被to_date函数替换。我可以以某种方式禁用它吗?这种格式较大,但是没有提供更多信息,因此我不需要它。 SQL Developer可以通过编程方式将其转换回吗?

2 个答案:

答案 0 :(得分:2)

这是Oracle在后台执行的操作,并且不是特殊的SQL Developer视图。格式无法修改:

SQL> explain plan for
  2  with rec (d) as (select sysdate from dual)
  3  select *
  4    from rec
  5   where d > date '2018-01-01';

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|*  1 |  FILTER          |      |       |            |          |
|   2 |   FAST DUAL      |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------

   1 - filter(SYSDATE@!>TO_DATE(' 2018-01-01 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss'))

15 rows selected.

您可以使用DBMS_XPLAN.DISPLAY() format 参数删除谓词信息,但不能修改其外观

SQL> select * from table(dbms_xplan.display(null, null, '-PREDICATE'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FILTER          |      |       |            |          |
|   2 |   FAST DUAL      |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------

9 rows selected.

答案 1 :(得分:1)

如其他答案所述,这就是Oracle重写String.format()字面量的方式。

例如,在使用DATE文字定义分区表时,如下所示。

DATE

...您会看到create table TEST (id NUMBER, PART_DATE DATE ) PARTITION BY RANGE (PART_DATE) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH')) ( PARTITION p1 VALUES LESS THAN (DATE'2018-08-01'), PARTITION p2 VALUES LESS THAN (DATE'2018-09-01'), PARTITION p3 VALUES LESS THAN (DATE'2018-10-01') ); 个分区中的HIGH_VALUES个函数:

to_date

重要内容-Oracle 了解 日期TO_DATE(' 2018-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') TO_DATE(' 2018-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') TO_DATE(' 2018-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

例如此查询...

value

...产生以下执行计划

select * from TEST where PART_DATE = DATE'2018-09-15';

请注意,----------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 22 | 2 (0)| 00:00:01 | | | | 1 | PARTITION RANGE SINGLE| | 1 | 22 | 2 (0)| 00:00:01 | 3 | 3 | |* 2 | TABLE ACCESS FULL | TEST | 1 | 22 | 2 (0)| 00:00:01 | 3 | 3 | ----------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("PART_DATE"=TO_DATE(' 2018-09-15 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) 谓词使用了FILTER函数调用,但是to_datePstart指向单个分区(#3)

这意味着,Oracle在基于DATE值进行解析时就知道将访问哪个分区(并且可以在优化过程中从中获利)。

因此,简而言之-是的,在日期字符串周围有一个函数调用,但这与列上的函数调用禁止索引访问的情况无法相比。

相反,在使用谓词Pstop访问上表时,您获得了指向PART_DATE = SYSDATE分区的执行计划。

KEY

这意味着Oracle知道它将仅访问一个分区,但是不知道哪个分区。