0

我编写了一个标量函数 ( 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)吗?如果是这样,这种方法将行不通。
4

2 回答 2

1

我猜问题不在于你的功能。尝试创建一个基于函数的索引trunc(ord.ordering_date)并查看解释计划。

 CREATE INDEX ord_date_index ON ord(trunc(ord.ordering_date));
于 2012-08-09T15:28:09.090 回答
1

如果计划的步骤相同,那么完成的工作总量应该相同。如果您跟踪会话(类似于set autotrace onSQL*Plus 中的简单操作或更复杂的操作,例如事件 10046 跟踪),或者DBA_HIST_SQLSTAT假设您已获得 AWR 表的许可访问权限,您是否看到(大致)相同数量的逻辑两个查询的 I/O 和 CPU 消耗?您看到的运行时差异是否可能是您运行第二个查询时缓存数据的结果?

于 2012-08-09T15:20:42.610 回答