是否有一种优化此查询的棘手方法

时间:2010-07-14 15:42:14

标签: oracle optimization date

我正在处理一个有3008698

的表

exam_dateDATE字段。

但我跑的查询只想匹配月份部分。所以我所做的是:

select * from my_big_table where to_number(to_char(exam_date, 'MM')) = 5;

我认为由于列上的功能需要很长时间。有没有办法避免这种情况并使其更快?除了对表格进行更改外?表中的exam_date具有不同的日期值。像01-OCT-10或12-OCT-10 ......等等

5 个答案:

答案 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的答案)或使用基于函数的索引。