【问题标题】:Why is there such a big difference in the execution time of a query ran by ADF and in SQL Developer为什么 ADF 和 SQL Developer 运行的查询的执行时间有如此大的差异
【发布时间】:2011-04-06 04:30:34
【问题描述】:

我的 JDeveloper ADF Web 应用程序中运行的查询存在一个奇怪的问题。它是一个向 Oracle 10g 数据库发出选择语句的简单搜索表单。提交搜索时,ADF 框架(首先)运行查询,(其次)运行包装在“select count(1) from (...query...)”中的相同查询——这里的目标是获取总行数,并显示“Next 10 个结果”导航控件。

到目前为止,一切都很好。麻烦来自我从第二个查询(其中包含“count(1)”的查询)中获得的令人发指的性能。为了调查这个问题,我在 SQL Developer 中复制/粘贴/运行了查询,并惊讶地看到更好的响应。

在比较 ADF 和 SQL Developer 中的查询执行时,我采取了所有措施来确保两种执行的环境具有代表性: - 新启动的数据库 - 与 OC4J 相同 这样我可以确定差异与缓存和/或缓冲无关,在这两种情况下,数据库和应用程序服务器都是新(重新)启动的。

我为这两个会话记录的痕迹说明了这种情况:

查询在 ADF 中运行:

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.97       0.97          0          0          0           0
Fetch        1     59.42     152.80      35129    1404149          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3     60.39     153.77      35129    1404149          0           1

SQL Developer 中的相同查询:

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      1.02       1.16          0          0          0           0
Fetch        1      1.04       3.28       4638       4567          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      2.07       4.45       4638       4567          0           1

提前感谢任何 cmets 或建议!

【问题讨论】:

  • 你能把执行计划也显示出来吗(EXPLAIN)?
  • 另外,只是为了确定 - 当您说您复制并粘贴 SQL 时,这是逐字记录还是您必须将绑定变量子句(来自框架)更改为文字(对于 SQL Developer)?
  • 解释计划确实会有所帮助,但我还是会大胆猜测。您在非空列上有索引吗?也许其中一个查询正在使用索引扫描,而另一个正在使用表扫描。是否有任何提示可能导致这种情况,或者缺少统计信息?
  • @dpbradley:好点。使用文字而不是绑定很可能会导致更有效的计划(对于严重倾斜的数据,这里可能就是这种情况,因为计数只返回一个可能是大表的表)。

标签: jdeveloper oracle-adf


【解决方案1】:

使用 count 的查询速度较慢,因为它必须读取所有数据(对其进行计数)。

当您运行另一个查询时,您只获取第一页数据,因此在您获得前十个结果后,执行(从光标读取)可以停止。

尝试使用您的第一个查询加载到第 100 页,它可能会比第一页慢得多。

如果在线选择计数过于昂贵,一个常见的技巧是选择多于您需要的一项(在您的情况下为 11 项)以确定是否有更多数据。您不能显示页数,但至少可以显示“下一页”按钮。

更新:您是说计数查询仅在通过 ADF 运行时很慢,但通过 SQL Developer 运行时很快?

【讨论】:

  • 一点澄清 - 我正在执行 ADF 运行的完全相同的查询,并在 SQL Developer 中执行它以进行比较(在具有空缓冲区和缓存的新启动的数据库实例上)。在这两种情况下,它都是一个带有计数的查询,传递所有数据,只返回行数。我同意它涉及大量的数据库读取,但为什么这两个客户端之间存在差异? Thilo,是的 - 在 SQL Developer 中运行时,ADF 中的慢查询(几乎一分钟!)只需要一秒钟。
  • 完全一样(准确地说,只计算 1 行)。
【解决方案2】:

如果是同一个查询,我可以想到:

  • ADF 与 SQL Developer 中的不同设置(您是否尝试过使用 SQL*Plus?)
  • 在慢速情况下绑定类型不正确的变量

但如果没有执行计划或 SQL,就很难说

【讨论】:

    【解决方案3】:

    多年来,我发现“SELECT COUNT...”通常会导致意外减速。

    如果我理解上面发布的结果,从 JDeveloper 查询需要 153 秒,但从 SQL Developer 只需大约 4.5 秒,您将使用此查询来确定是否应显示“下一个 10 个结果”控件.

    我不知道运行时间是 4.5 秒还是 153 秒是否重要——即使是最好的情况,初始化页面似乎也相当慢。假设您可以在从页面提交时让查询在 4.5 秒内响应 - 这仍然是让用户坐下来等待的时间很长,因为他们只需点击鼠标就可以开始做其他事情.在同样的 4.5 秒内,应用可能能够获取足够的数据来多次加载页面。

    我认为@Thilo 的想法是多获取一条记录来填充页面以确定是否有更多可用数据。也许这可以适应您的情况?

    分享和享受。

    【讨论】:

    • 但是,如果他说的是对的,在 SQL Developer 中运行时 count(*) 已经足够快了,并且只会在应用程序中变慢。
    【解决方案4】:

    好的,我终于找到了这种可怕行为的解释。长话短说,答案在 JDeveloper 中我的 ViewObject 的定义(调整参数)中。我缺少的是这两个重要参数:

    • FetchMode="FETCH_AS_NEEDED"
    • FetchSize="10"

    没有它们,会发生以下情况 - ADF 运行主查询、绑定变量并获取结果。然后,为了估计行数,它启动包含在“select count(1) from (my_query)”中的相同查询,但是......(鼓声)......没有绑定变量!!!在不考虑绑定变量的实际值的情况下估计行数有什么用,这真的让我大吃一惊!

    无论如何,这一切都在 ViewObject 的定义中:需要设置以下设置,以获得预期的行为:

    • 批次中的所有行:10
    • (选中)根据需要
    • (未选中)通过行集分页时填充行的最后一页

    执行计划对我没有帮助(ADF 和 SQL Developer 都是相同的),差异仅在使用绑定获取的跟踪文件中可见。

    所以,现在我的问题已经解决了 - 感谢所有提示,最终让我解决了问题!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      • 2016-11-21
      • 2018-11-07
      相关资源
      最近更新 更多