【问题标题】:Reducing Parse Calls in Oracle减少 Oracle 中的解析调用
【发布时间】:2011-09-06 05:30:34
【问题描述】:

我注意到 parse_calls 等于我们的 Oracle 11g 数据库中的执行次数。

 select parse_calls, executions
 from v$sql order by parse_calls desc;

运行上述查询会得到以下结果。

"PARSE_CALLS" "EXECUTIONS"
   87480        87480
   87475        87476
   87044        87044
   26662        26662
   21870        21870
   21870        21870

据我所知,这是一个主要的性能缺陷。所有这些 SQL 语句要么是存储过程,要么是使用绑定变量。我还重用了从 C# 调用存储过程的命令对象。

如何减少其中的解析调用次数?

另外,有什么方法可以区分硬解析和软解析吗?

编辑

正如@DCookie 提到的,我在数据库上运行了以下查询。

SELECT s2.name, SUM(s1.value)
FROM v$sesstat s1 join v$statname s2 on s1.statistic# = s2.statistic#
WHERE s2.name LIKE '%parse count%'
GROUP BY s2.name
ORDER BY 1,2;

结果如下

"NAME"                         "SUM(S1.VALUE)"
"parse count (describe)"             0
"parse count (failures)"             29
"parse count (hard)"                 258
"parse count (total)"                11471

所以硬解析的数量与解析的数量相比似乎非常低。感谢大家的回复:)

最终更新:

解析的主要问题是因为我们在连接字符串中关闭了连接池。打开连接池后,我能够完全解决解析问题。

【问题讨论】:

  • 我假设,存储过程已编译并且不运行EXECUTE IMMEDIATE 语句?
  • 是的。一切都编译好了。没有EXECUTE IMMEDIATE 声明。
  • 这可能与共享池设置有关,但我不记得如何检查。我相信这很快就会得到答复
  • 我会问 - 你能证实这是一个主要的性能缺陷吗?如堆栈样本所示,它是否超过挂钟时间的 10%?如果是 10%,那么即使你可以完全消除它,整体时间也只会减少 10%。
  • 我想是这样,但我总是鼓励人们以相对而非绝对的方式思考。不是因为这 10% 很小,而是因为问题的大小范围很广,你能看到的一个小问题可以将你的注意力从一个不太明显的大问题上转移开。然后,如果你能找到并修复大的那个,那么小那个现在会变得更大,按百分比计算,因为分母更小了。因此,如果您的解析成本为 10%,并且如果您还没有发现更大的问题,那么该代码非常接近最优,所以一定要追求 10%。

标签: c# sql performance oracle oracle11g


【解决方案1】:

从这里开始:

SELECT name, SUM(value)
  FROM v$sesstat s1 join v$statname s2 on s1.statistic# = s2.statistic#
 WHERE s1.name LIKE '%parse count%'
 GROUP BY name
 ORDER BY 1,2;

这将为您提供硬解析次数和总解析次数。查询中的 parse_calls 值是总解析,硬解析和软解析。

您的 SQL 是做什么的?没有太多的游标处理,主要是单个语句?您的执行与解析的比率几乎是 1-1,如果它们是软解析,则意味着您没有做太多的游标处理。

编辑:

除非您可以修改代码以打开并挂起每个 SQL 语句的游标,并在会话中尽可能多地重用它们,否则我认为您无法避免解析。

【讨论】:

  • 在我的 Oracle (10.2) 版本中,这些 statistic# 值不匹配任何内容。将谓词更改为WHERE name LIKE 'parse count%' 可能会更好。
  • @Dave,我使用的是 11g 数据库,OP 也是如此,所以它很可能会起作用。您的观点总体上仍然有效。
  • 谢谢。我会检查这个。是的,我没有做太多的光标处理。大部分是单个语句。
  • @Chathura,这可能是您看到 1-1 执行以进行解析的原因。只要您的查询使用绑定变量,解析很可能是软的,并且比硬解析的影响要小得多。
  • 如果单个 SQL 有数千次执行,那么几乎可以肯定是软解析。
【解决方案2】:

每次创建新游标时都必须进行解析调用,即使语句在库缓存中也是如此。检查库缓存的是解析调用。如果在库缓存中找到该语句,则为软解析。

@DCookie 已回答您关于检查硬解析计数与软解析计数的问题。我希望您会发现大多数解析调用都是软解析。请注意,您不应期望从v$sysstat 返回的计数非常接近来自v$sql 的总解析调用,因为前者是自实例启动以来的计数,而后者仅显示当前在库缓存中的语句.

完全避免解析调用的唯一方法是保留现有游标的句柄,并在需要时执行它,并在适当时绑定新值。这有时会通过缓存游标而发生——它超出了您的明确控制范围,尽管我相信您可以更改一些参数来影响它。在 PL/SQL 代码中,您可以显式保留使用 DBMS_SQL 包创建和管理的游标。我希望 C# 有相应的能力。

无论如何,您正在查看的内容可能不是问题。仅仅因为计数看起来很高并不意味着解析是您​​系统的瓶颈。

首先,您应该检查具有高解析计数的 SQL 语句是否在您的控制范围内。当我在我的一个系统上对您的查询进行修改版本时:

select parse_calls, executions, parsing_schema_name,sql_text
 FROM v$sql
 ORDER BY parse_calls DESC;

我发现解析调用次数最多的语句都是SYS解析的递归SQL。根据您的使用情况,您可能不是这种情况,但需要检查一下。

【讨论】:

  • 所有具有高解析计数的 SQL 语句都在我的控制范围内。我在故意发布问题时从查询和结果中删除了sql_text 部分:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多