Oracle 9i - 优化器与日期算术有关的问题?
我们有一个查询,其中包括(但具有其他联接、表和 where 条件):
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;
如果我们:
- 将
SubscribedDateTo
值转换为to_date('2011-07-16', 'yyyy-mm-dd')
(即在查询之外进行算术), - 将
SubscribedDateTo
设为字符串并使用“to_date('SubscribedDateTo', 'yyyy-mm-dd')
+ 1" 作为WHERE
中的第二个条件。
然后,查询速度显着加快(<1 秒 vs. 44+ 秒)。
进一步信息:
- 在查询上运行解释计划会出现错误
ORA-00932:不一致的数据类型:期望的DATE得到NUMBER
subscribed_date
列有索引和统计信息等 在trunc()
调用中包装SubscribedDateTo + 1
运行- 不会影响性能
- 我们没有具有类似数据量等的非 9i 数据库来测试是否是否是Oracle的版本。
问题是:我们无法找到任何信息明确表明 Oracle 9i 优化器对这种日期运算存在问题。这是这里发生的事情还是还有其他事情发生?
We have a query that includes (but has other joins, tables and where conditions):
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
called from a Java application.
The ?
paramaters allow checking for orders submitted between two dates.
However, this query runs very slowly.
We converted to run from PL/SQL for testing as follows:
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;
IF we either:
- convert the
SubmittedDateTo
value toto_date('2011-07-16', 'yyyy-mm-dd')
(i.e. do the arithmetic outside the query), - make
SubmittedDateTo
a string and use "to_date('SubmittedDateTo', 'yyyy-mm-dd')
+ 1" as the second condition in theWHERE
.
THEN, the query speeds up dramatically ( < 1 second vs. 44+ seconds).
Further information:
- running an explain plan on the query gives the error
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
- the
submitted_date
column has an index and stats, etc. have been run - wrapping the
SubmittedDateTo + 1
in atrunc()
call does not affect performance - We do not have a non-9i database with similar data volumes, etc. to test if it's the version of Oracle or not.
The question is: we are unable to find any information which clearly states that the Oracle 9i Optimizer has an issue with this kind of date arithmetic. Is that what's happening here or is there something else going on?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我始终确保所有转换都显式处理(并假设 o.subscribed_date 是 DATE 数据类型):
这确保任何隐式转换中没有错误,并且所有转换在其数据类型中都是显而易见的。
“问题是:我们无法找到任何信息明确表明 Oracle 9i 优化器在这种日期算术方面存在问题。这是这里发生的情况还是还有其他问题?”
我不认为它是优化器,它可能是隐式转换的最终产品导致了性能问题。由于我们没有 Oracle 数据库中的日期等 NLS 设置,因此很难判断,但如果使用显式转换可以提高性能,那么我建议您使用它们(而且也是更好的练习)。
希望它有帮助,奥利。
I'd always ensure that all conversions are handled explicitly (and assuming o.submitted_date is a DATE datatype):
This ensures there is no errors in any implicit conversions and all conversions are obvious in their data type.
"The question is: we are unable to find any information which clearly states that the Oracle 9i Optimizer has an issue with this kind of date arithmetic. Is that what's happening here or is there something else going on?"
I don't think it is the optimiser, it could be the end product of your implicit conversions are causing the performance issues. As we do not have you NLS settings for dates etc from the Oracle database it'd be hard to tell but if using explicit conversions increases performance, then I'd suggest you use them (and it's better pracitce too).
Hope it helps, Ollie.
根据 Oracle 文档(这是 v10 ,但我想这也适用于 9i),“...不支持执行日期绑定变量隐式类型转换的语句的 EXPLAIN PLAN。”
除了 Ollie 建议的方法之外,您是否尝试过使用 trunc() resp。之间而不是?
分别。
According to the Oracle documentation (this is v10, but I guess this applies to 9i as well), "...does not support EXPLAIN PLAN for statements performing implicit type conversion of date bind variables."
Apart from the approach sugggested by Ollie, have you tried using trunc() resp. between instead?
resp.