我们有一个与Oracle 10g交谈的.NET应用程序。我们的DBA最近提取了一个查询列表,其中执行等于parse_calls。我们假设这有助于我们在代码中找到所有未参数化的查询。
出乎意料的是,以下查询显示在此列表的顶部附近,有1,436,169次执行和1,436,151次解析:
SELECT bar.foocolumn
FROM bartable bar,
baztable baz
WHERE bar.some_id = :someId
AND baz.another_id = :anotherId
AND baz.some_date BETWEEN bar.start_date AND (nvl(bar.end_date, baz.some_date + (1/84600)) - (1/84600))
为什么执行等于此查询的parse_calls?
答案 0 :(得分:3)
可能是因为.NET程序员选择在伪代码中编写这样的例程:
Loop over someId's and anotherId's
parse(your_query);
bind someId and anotherId to your_query;
execute(your_query);
close(your_query);
end loop;
他们应该像这样编码:
parse(your_query);
Loop over someId's and anotherId's
bind someId and anotherId to your_query;
execute(your_query);
end loop;
close(your_query);
甚至更好:使用单个查询来检索所有someId / anotherId的所有数据
此致 罗布。
答案 1 :(得分:3)
解析查询的次数完全取决于调用应用程序。每次应用程序要求数据库解析时,都会解析一次查询。
服务器端,有different kinds of parse:
HARD解析 - 查询永远不会 以前见过,不是在分享 池。我们必须解析它,哈希它, 查看共享池,不要 找到它,安全检查,优化 它等等(很多工作)。
SOFT解析 - 查询已经完成 之前看到的是在共享池中。我们 必须解析它,哈希它,看看 它的共享池并找到它 (较少的工作然后是硬解析但工作 (尽管如此)
在您的情况下,您最有可能每个会话创建一次语句,然后将其丢弃,以便Oracle每次都必须解析它。但是,由于参数化,这个解析是一个软解析,而Oracle只需要进行一次优化的昂贵步骤。
但是,你可以在你的应用程序中缓存该语句并重用它,以便(软)每次会话只解析一次。