我们有一个包含(但有其他连接,表和条件)的查询:
SELECT
o.contact_id,
o.completed_date,
o.submitted_date
FROM
orders o /* 860,000 row table */
WHERE
? <= o.submitted_date
AND o.submitted_date < ? + 1
从Java应用程序调用。
?
参数允许检查两个日期之间提交的订单。
但是,此查询运行速度非常慢。
我们转换为从PL / SQL运行以进行测试,如下所示:
SubmittedDateFrom date:=to_date('2011-07-15', 'yyyy-mm-dd');
SubmittedDateTo date:=to_date('2011-07-15', 'yyyy-mm-dd');
CURSOR c_orgs IS
SELECT
o.contact_id,
o.completed_date,
o.submitted_date
FROM
orders o
WHERE
SubmittedDateFrom <= o.submitted_date
AND o.submitted_date < SubmittedDateTo + 1;
BEGIN
FOR c_o IN c_orgs LOOP
DBMS_OUTPUT.put_line('Submitted date = '||c_o.submitted_date);
END LOOP;
END;
如果我们要么:
SubmittedDateTo
值转换为to_date('2011-07-16', 'yyyy-mm-dd')
(即在查询外执行算术),SubmittedDateTo
作为字符串,并使用“to_date('SubmittedDateTo', 'yyyy-mm-dd')
+ 1”作为WHERE
中的第二个条件。然后,查询速度急剧上升(<1秒对44秒)。
更多信息:
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
submitted_date
列有一个索引和统计信息等已经运行SubmittedDateTo + 1
包裹在trunc()
电话中不会影响效果问题是:我们无法找到任何明确说明Oracle 9i Optimizer存在此类日期算术问题的信息。这是在这里发生的事情还是还有其他事情发生?
答案 0 :(得分:1)
我总是确保明确处理所有转换(假设o.submitted_date是DATE数据类型):
DECLARE
CURSOR c_orgs
IS
SELECT o.contact_id,
o.completed_date,
o.submitted_date
FROM orders o
WHERE o.submitted_date BETWEEN TO_DATE(SubmittedDateFrom, 'yyyy-mm-dd')
AND TO_DATE(SubmittedDateTo, 'yyyy-mm-dd');
BEGIN
FOR c_o IN c_orgs
LOOP
DBMS_OUTPUT.put_line('Submitted date = '||c_o.submitted_date);
END LOOP;
END;
这可以确保任何隐式转换都没有错误,并且所有转换在其数据类型中都很明显。
“问题是:我们无法找到任何明确说明Oracle 9i Optimizer存在此类日期算术问题的信息。这是发生在这里的事情还是还有其他事情发生?”
我不认为它是优化者,它可能是隐式转换的最终产品导致性能问题。由于我们没有从Oracle数据库中获取日期等的NLS设置,因此很难说,但如果使用显式转换可以提高性能,那么我建议您使用它们(这也是更好的实践)。
希望它有所帮助,奥利。
答案 1 :(得分:1)
根据Oracle documentation(这是v10,但我想这也适用于9i),“...不支持EXPLAIN PLAN用于执行日期绑定变量的隐式类型转换的语句。”
除了Ollie提出的方法之外,您是否尝试过使用trunc()resp。之间相反?
SELECT
o.contact_id,
o.completed_date,
o.submitted_date
FROM
orders o /* 860,000 row table */
WHERE
trunc(o.submitted_date) = trunc(?)
RESP。
SELECT
o.contact_id,
o.completed_date,
o.submitted_date
FROM
orders o /* 860,000 row table */
WHERE
o.submitted_date between ? and ? + 1