我编写了一个标量函数 ( DYNAMIC_DATE
),它将文本值转换为日期/时间。例如,DYANMIC_DATE('T-1')
(T-1 = today - 1 = 'yesterday') 返回08-AUG-2012 00:00:00
。它还接受日期字符串:DYNAMIC_DATE('10/10/1974')
.
该函数使用CASE
语句来解析唯一参数并计算相对于sysdate
.
虽然它不使用其模式中的任何表,但它确实使用TABLE
类型来存储日期格式字符串:
TYPE VARCHAR_TABLE IS TABLE OF VARCHAR2(10);
formats VARCHAR_TABLE := VARCHAR_TABLE ('mm/dd/rrrr','mm-dd-rrrr','rrrr/mm/dd','rrrr-mm-dd');
当我在SELECT
子句中使用该函数时,查询会在 < 1 秒内返回:
SELECT DYNAMIC_DATE('MB-1') START_DATE, DYNAMIC_DATE('ME-1') END_DATE
FROM DUAL
如果我将它用于我们的日期维度表(总共 91311 条记录),查询将在 < 1 秒内完成:
SELECT count(1)
from date_dimension
where calendar_dt between DYNAMIC_DATE('MB-1') and DYNAMIC_DATE('ME-1')
但是,如果将函数用于更大的表(26,301,317 条记录),则其他函数会出现问题:
/*
cost: 148,840
records: 151,885
time: ~20 minutes
*/
SELECT count(1)
FROM ORDERS ord
WHERE trunc(ord.ordering_date) between DYNAMIC_DATE('mb-1') and DYNAMIC_DATE('me-1')
但是,使用“硬编码”日期的相同查询返回得相当快:
/*
cost: 144,257
records: 151,885
time: 62 seconds
*/
SELECT count(1)
FROM ORDERS ord
WHERE trunc(ord.ordering_date) between to_date('01-JUL-2012','dd-mon-yyyy') AND to_date('31-JUL-2012','dd-mon-yyyy')
供应商的香草安装不包括ORDERING_DATE
现场索引。
这两个查询的解释计划是相似的:
带功能:
带有硬编码日期:
- 子句 中是否
DYNAMIC_DATE
重复调用函数?WHERE
- 还有什么可以解释这种差异?
** 编辑 **
NONUNIQUE
向 ORDERS 表添加了索引。两个查询都在 < 1 秒内执行。两种方案是相同的(方法),但具有功能的方案成本更低。
我DETERMINISTIC
从函数中删除了关键字;查询在 < 1 秒内执行。
- 问题真的与函数有关还是与表格有关?
- 3年后,当这个表更大时,如果我不包含
DETERMINISTIC
关键字,查询性能会受到影响吗? DETERMINISTIC
关键字会对函数的结果有任何影响吗?如果我DYNAMIC_DATE('T-1')
明天运行,我会得到与今天运行相同的结果(08/09/2012)吗?如果是这样,这种方法将行不通。