简单的字符串比较条件使查询运行时间更长

时间:2019-06-22 00:02:51

标签: sql oracle oracle12c

在第一次运行时,从下面的代码中查询#1需花费1-2秒的时间,第二次则需要0.1秒。同时,查询#2和#3总是在0.1-0.2秒内执行。有这种行为的任何解释吗?我会理解是否由于#1中的错误条件而反之亦然。

我尚未提供执行计划,因为该视图有点复杂,并且不确定计划本身是否会有所帮助。但是,如果确实需要,我会

1

SELECT
doc_id, line_num, load_id, ord_qty
FROM someview v
WHERE doc_id = 2987541 and 'A'='X' and v.iter_num = 
(select max(iter_num) from someview where doc_id=v.doc_id);

2

SELECT
doc_id, line_num, load_id, ord_qty
FROM someview v
WHERE doc_id = 2987541 and v.iter_num = 
(select max(iter_num) from someview where doc_id=v.doc_id);

3

SELECT
doc_id, line_num, load_id, ord_qty
FROM someview v
WHERE doc_id = 2987541 and 'X'='X' and v.iter_num = 
(select max(iter_num) from someview where doc_id=v.doc_id);

1 个答案:

答案 0 :(得分:0)

查询1的运行时差异可能是由于硬解析和/或冷缓冲区高速缓存引起的。

第一次运行后,已解析的查询缓存在共享池中,并且数据块已被读取到共享内存中的缓冲区缓存中(假设由于系统繁忙,它们不会立即老化)。因此,第二轮及以后的运行通常应该更快。您可以通过运行查询,从共享池中清除关联的游标,再次运行它并查看运行时是否保持1-2秒,来测试查询#1较长的初始运行时是否是由于硬解析引起的。尽管可以通过ALTER SYSTEM FLUSH SHARED POOL命令清除整个共享池,但侵入性较小的方法是清除特定的游标。下面的参考资料显示了如何执行此操作。

DBMS_SHARED_POOL.PURGE

How to flush a single object from the shared pool

或者,您可以跟踪会话,并使用tkprof查看在查询#1的解析,执行和获取阶段中花费了多少时间,并将结果与​​后续运行进行比较。有关详细信息,请参见下面的参考。

SQL trace and TKPROF

对于查询2和3,如果您在查询1之后立即运行它们,则由于查询1已经预热了缓存,它们的运行速度可能会更快。不幸的是,没有一种简单的方法可以像从共享池中解析语句那样,选择性地从缓冲区高速缓存中清除数据块。尽管ALTER SYSTEM FLUSH BUFFER CACHE语句可以清除缓存,但在生产系统上执行此操作确实不是一个好主意,因为在重新填充缓存时,它可能导致物理I / O急剧增加。在隔离的非生产系统上执行此操作可能是可以接受的。

返回到解析,查询#3可能能够使用与#1相同的解析查询,具体取决于如何设置cursor_sharing参数,这将大大节省解析时间。

CURSOR_SHARING parameter

最后,tkprof和此答案中引用的其他工具需要数据库中提升的特权,因此您可能需要DBA的帮助。