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

Nic*_*lás 4 sql oracle performance where-clause

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

select id, name
from customer
where period_aded = to_char(paramDate,'mm/yyyy')
Run Code Online (Sandbox Code Playgroud)

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

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

这应该意味着我应该在将这些值添加到查询之前转换它们.

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

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

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

谢谢你的回答

Thi*_*ilo 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')))
Run Code Online (Sandbox Code Playgroud)

有关用户定义的函数,请查看本文.它提到了两种方法来确保只调用一次函数:

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

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

    SELECT COUNT(*)FROM EMPLOYEES WHERE SALARY =(SELECT getValue(1)FROM DUAL);