我正在处理一个有3008698
行
exam_date
是DATE
字段。
但我跑的查询只想匹配月份部分。所以我所做的是:
select * from my_big_table where to_number(to_char(exam_date, 'MM')) = 5;
我认为由于列上的功能需要很长时间。有没有办法避免这种情况并使其更快?除了对表格进行更改外?表中的exam_date
具有不同的日期值。像01-OCT-10或12-OCT-10 ......等等
答案 0 :(得分:5)
我不了解Oracle,但是做什么
WHERE exam_date BETWEEN first_of_month AND last_of_month
其中两个日期是常量表达式。
答案 1 :(得分:3)
select * from my_big_table where MONTH(exam_date) = 5
哎呀..甲骨文啊?
select * from my_big_table where EXTRACT(MONTH from exam_date) = 5
答案 2 :(得分:3)
请记住,由于您需要大约所有数据的十二分之一,因此Oracle无论如何都可能更有效地执行全表扫描。这可以解释为什么当你遵循harpo的建议时表现更差。
为什么呢?假设您的数据是20行适合每个数据库块(平均),因此您总共有3,000,000 / 20 = 150,000个块。这意味着全表扫描将需要150,000个块读取。现在,3,000,000行中约有1/12将是05个月.3,000,000 / 12是250,000。因此,如果您使用索引,则会有250,000个表读取 - 并且忽略了也需要的索引读取。因此,在此示例中,全表扫描比索引搜索的工作少得多。
答案 3 :(得分:3)
坚持认为MONTH只有十二个不同的值。因此,除非你有一个强聚类的记录集(比如你是否使用了partitioining),否则使用索引可能不一定是以这种方式查询的最有效方式。
我没有发现使用EXTRACT()导致优化器在我的日期列上使用常规索引但是YMMV:
SQL> create index big_d_idx on big_table(col3) compute statistics
2 /
Index created.
SQL> set autotrace traceonly explain
SQL> select * from big_table
2 where extract(MONTH from col3) = 'MAY'
3 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 23403 | 1028K| 4351 (3)| 00:00:53 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 23403 | 1028K| 4351 (3)| 00:00:53 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(EXTRACT(MONTH FROM INTERNAL_FUNCTION("COL3"))=TO_NUMBER('M
AY'))
SQL>
在这些场景中,可以说服优化器使用索引的是构建基于函数的索引:
SQL> create index big_mon_fbidx on big_table(extract(month from col3))
2 /
Index created.
SQL> select * from big_table
2 where extract(MONTH from col3) = 'MAY'
3 /
Execution Plan
----------------------------------------------------------
Plan hash value: 225326446
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 23403 | 1028K| 475 (0)|00:00:06|
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 23403 | 1028K| 475 (0)|00:00:06|
|* 2 | INDEX RANGE SCAN | BIG_MON_FBIDX | 9361 | | 382 (0)|00:00:05|
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(EXTRACT(MONTH FROM INTERNAL_FUNCTION("COL3"))=TO_NUMBER('MAY'))
SQL>
答案 4 :(得分:1)
函数调用意味着Oracle将无法使用可能在列上定义的任何索引。
删除函数调用(如harpo的答案)或使用基于函数的索引。