使用where子句中的函数的Oracle性能

时间:2009-07-13 01:03:16

标签: sql oracle where-clause performance

在存储过程(其日期参数名为'paramDate')中,我有一个像这样的查询

select id, name
from customer
where period_aded = to_char(paramDate,'mm/yyyy')

Oracle会将paramDate转换为每行的字符串吗?

我确信Oracle不会,但我被告知Oracle会。 事实上,我认为如果函数的参数是约束(在查询中没有获得fierld或计算值),结果应该总是相同的,这就是Oracle应该只执行一次此转换的原因。 然后我意识到我有时会在几个函数中执行DML语句,这可能会导致结果值发生变化,即使每行都没有变化。

这应该意味着我应该在将这些值添加到查询之前对其进行转换。

无论如何,也许好的“已知函数”(内置)会被评估一次,甚至我的函数也会被评估。

无论如何,再次......

oracle会执行一次to_char还是Oracle会为每一行执行该操作?

感谢您的回答

3 个答案:

答案 0 :(得分:8)

我认为通常不会这样,因为它会阻止使用索引。

至少对于内置函数,Oracle应该能够确定它只能评估一次。 (对于用户定义的函数,请参见下文)。

以下是使用索引的情况(并且不对每一行评估函数):

SQL> select id from tbl_table where id > to_char(sysdate, 'YYYY');

--------------------------------------------------------------------------------
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |             |    35 |   140 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| SYS_C004274 |    35 |   140 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("ID">TO_NUMBER(TO_CHAR(SYSDATE@!,'YYYY')))

对于用户定义的功能,请查看此article。它提到了两种确保方法 您的函数只被调用一次:

  1. 从Oracle 10.2开始,您可以将函数定义为DETERMINISTIC。

  2. 在旧版本中,您可以重新使用它来使用“标量子查询缓存”:

    SELECT COUNT(*)   来自员工   WHERE SALARY =(SELECT getValue(1)FROM DUAL);

答案 1 :(得分:1)

对to_char的担忧并没有给我敲响声。但是,在你的pl / sql中, 你可能有

create or replace procedure ........
  some_variable varchar2(128);
begin

  some_variable := to_char(paramDate,'mm/yyyy');

  -- and your query could read

  select id, name from customer where period_aded = some_variable;
.
.
.
end;
/

的Kt

答案 2 :(得分:1)

查看关于DETERMINISTIC关键字(here is onehere is another)的文章,介绍它是为了让开发人员告诉Oracle该函数将为相同的输入参数返回相同的值。因此,如果您希望只调用一次函数,并且可以保证它们将始终为相同的输入参数返回相同的值,您可以使用关键字DETERMINISTIC。

关于像to_char这样的内置函数,我会让那些精通Oracle内部的人给你指路。