Oracle Bind Query 很慢

Posted

技术标签:

【中文标题】Oracle Bind Query 很慢【英文标题】:Oracle Bind Query is very slow 【发布时间】:2015-02-10 15:00:03 【问题描述】:

我有一个 Oracle 绑定查询,它在我的 C# 程序中执行时非常慢(大约 2 分钟),但在 SQL Developer 中运行得非常快。它有两个命中表索引的参数:

select t.Field1, t.Field2
from theTable t
where t.key1=:key1
  and t.key2=:key2

另外,如果我删除绑定变量并创建动态 sql,它会像在 SQL Developer 中一样运行。

有什么建议吗?

顺便说一句,我正在使用 ODP。

【问题讨论】:

我想知道这是否与 c# vs sql developer 中的不同优化器设置(例如 first_rows vs all_rows)有关。请参阅this article by Tom Kyte 了解更多信息。也许您可以检查 v$sql 和 v$sql_shared_cursor 以查看同一条 sql 语句是否有多行,如果是,是否存在不同的优化器模式? 【参考方案1】:

如果您在 sql developer 中用静态变量替换绑定变量,那么您实际上并没有运行相同的测试。确保你使用绑定变量,如果它也很慢,你只是被一个糟糕的缓存执行计划所困扰。更新该表上的统计信息应该可以解决它。

但是,如果您实际上在 sql 开发人员中使用绑定变量,请继续阅读。 TLDR 版本是 ODP.net 运行的参数有时会导致稍微悲观的方法。从更新统计信息开始,但让您的 dba 捕获两种方案下的执行计划并进行比较以确认。

我从这里转发我的答案:https://***.com/a/14712992/852208 我考虑将你的标记为重复,但你的标题更简洁一些,因为它标识查询在 sql developer 中运行得很快。我会欢迎以其他方式处理的建议。

将以下内容添加到您的配置中会将 odp.net 跟踪信息发送到日志文件:

这可能只有在您能及时找到较大的时间间隔时才有用。很有可能确实有行进来,只是速度较慢。

尝试将“enlist=false”添加到您的连接字符串中。我不认为这是一个解决方案,因为它有效地禁用了分布式事务,但它应该可以帮助您隔离问题。您可以从 oracle 论坛帖子中获得更多信息:

从 ODP 的角度来看,我们真正能指出的是, 行为发生在 OCI_ATR_EXTERNAL_NAME 和 OCI_ATR_INTERNAL_NAME 在底层 OCI 连接上设置(当 distrib tx 支持已启用)。

我猜你没有看到的是 odp.net 调用和 sql 开发者调用之间的执行计划实际上是不同的(意味着实际的性能损失实际上发生在服务器上)。让您的 dba 跟踪连接并从 odp.net 调用和直接从 SQL Developer 调用(或使用 enlist=false 参数)获取执行计划。

如果您确认不同的执行计划,或者如果您想在黑暗中先发制人,请更新相关表的统计信息。在我的例子中,这纠正了这个问题,表明执行计划的生成并没有真正遵循针对不同类型连接的不同规则,但是当可能涉及分布式事务时,成本分析稍微悲观一些。强制执行计划的查询提示也是一种选择,但只能作为最后的手段。

最后,可能是网络问题。如果您的 odp.net 安装使用的是新的 oracle 主目录(除非您进行了一些安装后配置,否则我会期望它),那么 tnsnames.ora 可能会有所不同。 tnsnams 中的主机名可能不是完全限定的,从而造成解析服务器的更多延迟。在这种情况下,我只希望第一次尝试(而不是后续尝试)会很慢,所以我认为这不是问题,但我认为应该提到它。

【讨论】:

我正在从应用程序中复制 sql 并保持绑定变量完好无损。【参考方案2】:

参数是否绑定到 C# 中的正确数据类型? key1key2 列是数字,但参数 :key1:key2 是字符串?如果是这样,查询可能会返回正确的结果,但需要隐式转换。这种隐式转换就像使用函数to_char(key1),它会阻止使用索引。

【讨论】:

字段 key1 和 key2 分别是 CHAR(8) 和 CHAR(2)。参数也是 CHAR(8) 和 CHAR(2)。【参考方案3】:

还请检查查询返回的行数。如果数字很大,则可能 C# 正在获取所有行,而其他工具仅获取第一个口袋。在这种情况下,获取所有行可能需要更多的磁盘读取,这会更慢。要检查这一点,请尝试在 SQL Developer 中运行:

SELECT COUNT(*) FROM (
    select t.Field1, t.Field2
      from theTable t
     where t.key1=:key1
       and t.key2=:key2
)

上面的查询应该获取最大数量的数据库块。

在这种情况下不错的工具是 tkprof 实用程序,它显示 SQL 执行计划,在上述情况下可能会有所不同(但不应该如此)。

您也可能不小心连接到不同的数据库。在这种情况下,最好比较查询的结果。

由于您提出“绑定很慢”,我假设您已经检查了没有绑定的 SQL,而且它很快。在 99% 的情况下,使用绑定可以让事情变得更好。请检查使用常量的查询是否会快速运行。如果是,则问题可能是 key1 或 key2 列的隐式转换(例如 t.key1 是一个数字, :key1 是一个字符串)。

【讨论】:

记录数少。在 10 到 100 之间。

以上是关于Oracle Bind Query 很慢的主要内容,如果未能解决你的问题,请参考以下文章

win10电脑打开此电脑资源管理器任务管理器软件等突然很慢很慢,cup内存磁盘利用率却很低

SAP migo这个事物代码在做操作的时候,多人操作同一个事务代码时很慢很慢,是啥原因?

jsp做的网页,用tomcat测试时读数据库数据时很慢很慢,是啥原因?

Oracle Forms - “execute_query”命令很慢

公司网络很慢很卡的原因分析与处理

read by other session导致oracle性能低