【问题标题】:performance difference between to_char and to_date [duplicate]to_char 和 to_date 之间的性能差异 [重复]
【发布时间】:2013-12-16 05:47:50
【问题描述】:

我在 Oracle 10g 上有简单的 SQL 查询。我想知道这些查询之间的区别:

select * from employee where id = 123 and 
          to_char(start_date, 'yyyyMMdd') >= '2013101' and 
          to_char(end_date, 'yyyyMMdd') <= '20121231';

select * from employee where id = 123 and 
          start_date >= to_date('2013101', 'yyyyMMdd') and 
          end_date <= to_date('20121231', 'yyyyMMdd');

问题: 1. 这些查询是否相同? start_date、end_date 是索引日期列。 2. 一个比另一个更好用吗?

请告诉我。谢谢。

【问题讨论】:

    标签: sql oracle10g


    【解决方案1】:

    后者几乎肯定会更快。

    • 它避免了列值的数据类型转换。
    • Oracle 将更好地估计两个日期之间可能值的数量,而不是表示日期的两个字符串。

    请注意,两者都不会返回任何行,因为根据您给出的数字,下限可能有意高于上限。你也错过了 2013101 中的一个数字。

    【讨论】:

      【解决方案2】:

      WHERE 子句中的columns 转换、转换或转换为表达式(即“NVL”、“COALESCE”等)时的最大缺陷之一 CBO 将无法在该列上使用索引。我稍微修改了您的示例以显示差异:

      SQL> create table t_test as
        2    select * from all_objects;
      Table created
      SQL> create index T_TEST_INDX1 on T_TEST(CREATED, LAST_DDL_TIME);
      Index created
      

      为我们的实验创建表和索引。

      SQL> execute dbms_stats.set_table_stats(ownname => 'SCOTT',
                                              tabname => 'T_TEST',
                                              numrows => 100000,
                                              numblks => 10000);
      PL/SQL procedure successfully completed
      

      我们让 CBO 认为我们的桌子有点大。

      SQL> explain plan for
        2  select *
        3    from t_test tt
        4   where tt.owner = 'SCOTT'
        5     and to_char(tt.last_ddl_time, 'yyyyMMdd') >= '20130101'
        6     and to_char(tt.created, 'yyyyMMdd') <= '20121231';
      Explained
      SQL> select * from table(dbms_xplan.display);
      PLAN_TABLE_OUTPUT
      --------------------------------------------------------------------------------
      Plan hash value: 2796558804
      ----------------------------------------------------------------------------
      | Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
      ----------------------------------------------------------------------------
      |   0 | SELECT STATEMENT  |        |     3 |   300 |  2713   (1)| 00:00:33 |
      |*  1 |  TABLE ACCESS FULL| T_TEST |     3 |   300 |  2713   (1)| 00:00:33 |
      ----------------------------------------------------------------------------
      

      使用全表扫描,这在大表上成本很高。

      SQL> explain plan for
        2  select *
        3    from t_test tt
        4   where tt.owner = 'SCOTT'
        5     and tt.last_ddl_time >= to_date('20130101', 'yyyyMMdd')
        6     and tt.created <= to_date('20121231', 'yyyyMMdd');
      Explained
      SQL> select * from table(dbms_xplan.display);
      PLAN_TABLE_OUTPUT
      --------------------------------------------------------------------------------
      Plan hash value: 1868991173
      -------------------------------------------------------------------------------------------
      | Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
      --------------------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT            |              |     3 |   300 |     4   (0)| 00:00:01 |
      |*  1 |  TABLE ACCESS BY INDEX ROWID| T_TEST       |     3 |   300 |     4   (0)| 00:00:01 |
      |*  2 |   INDEX RANGE SCAN          | T_TEST_INDX1 |     8 |       |     3   (0)| 00:00:01 |
      ---------------------------------------------------------------------------------------------
      

      看,现在是索引范围扫描,成本明显降低。

      SQL> drop table t_test;
      Table dropped
      

      终于打扫了。

      【讨论】:

        【解决方案3】:

        用于输出(显示)目的使用 to_char

        对于“日期”处理(插入、更新、比较等)使用 to_date

        我没有任何性能链接可以分享,但是在上面的查询中使用 to_date 应该会运行得更快!

        虽然 to_char 它将首先转换日期,然后进行比较,它需要将其解析为日期类型。会有一点性能损失。

        使用to_date不需要先强制转换,直接使用日期类型。

        【讨论】:

          猜你喜欢
          • 2020-02-11
          • 2019-03-13
          • 2011-07-23
          • 1970-01-01
          • 1970-01-01
          • 2019-09-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多