我在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.一个人比另一个好吗?
请告诉我。谢谢。
答案 0 :(得分:2)
后者几乎肯定会更快。
请注意,根据您给出的数字,两者都不会返回任何行,因为下限可能意图高于上限。你也错过了2013101的数字。
答案 1 :(得分:2)
在 WHERE子句中转换,转换或转换为表达式(即“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
最后清洁。
答案 2 :(得分:0)
用于输出(显示)目的使用to_char
用于“日期”处理(插入,更新,比较等)使用to_date
我没有任何性能链接可以共享,但在上面使用to_date查询应该运行得更快!
虽然to_char将首先投射日期然后进行比较,但它需要将其解析为日期类型。性能损失会很小。
使用to_date时,它不需要先进行强制转换,它将直接使用日期类型。