我编写了一个标量函数(DYNAMIC_DATE
),用于将文本值转换为日期/时间。例如,DYANMIC_DATE('T-1')
(T-1 =今天减去1 ='昨天')返回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')
供应商的vanilla安装不包括ORDERING_DATE
字段的索引。
两个查询的解释计划类似:
功能:
具有硬编码日期:
DYNAMIC_DATE
子句中是否重复调用WHERE
函数? **编辑**
在ORDERS表中添加了NONUNIQUE
索引。两个查询都在< 1秒。两个计划都是相同的(方法),但具有该功能的计划是较低的成本。
我从该函数中删除了DETERMINISTIC
关键字;在<中执行的查询1秒。
DETERMINISTIC
关键字,查询效果会受到影响吗?DETERMINISTIC
关键字对函数的结果有影响吗?如果我明天运行DYNAMIC_DATE('T-1')
,我会得到与今天(2012年9月8日)运行时相同的结果吗?如果是这样,这种方法将无效。答案 0 :(得分:1)
如果计划的步骤相同,那么完成的工作总量应该相同。如果您跟踪会话(像SQL * Plus中的set autotrace on
那样简单,或者像事件10046跟踪那样更复杂),或者如果您看DBA_HIST_SQLSTAT
假设您拥有对AWR表的许可访问权限,那么您是否(大致)看到两个查询的逻辑I / O和CPU消耗量相同?您运行的运行时差异是否可能是运行第二个查询时缓存数据的结果?
答案 1 :(得分:1)
我猜这个问题与你的功能无关。尝试在trunc(ord.ordering_date)
上创建基于函数的索引并查看解释计划。
CREATE INDEX ord_date_index ON ord(trunc(ord.ordering_date));