将 Oracle 的行大小设置得更高会使我的应用程序变慢?

Posted

技术标签:

【中文标题】将 Oracle 的行大小设置得更高会使我的应用程序变慢?【英文标题】:Setting Oracle size of row fetches higher makes my app slower? 【发布时间】:2012-03-02 11:21:20 【问题描述】:

详细here 和确认here,Oracle 在通过 JDBC 查询数据时返回的默认行数是 10。我正在开发一个应用程序,它必须读取和比较我们的大量数据数据库。我认为如果我们只是将defaultRowPrefetch 增加到 1000 左右,那么我们的应用程序肯定会运行得更快。事实证明,它执行速度较慢,大​​约下降了 20%。

然后我们决定慢慢地从 10 增加这个数字,看看它的表现如何。通过将其设置在 100 到 200 之间,我们已经看到了大约 10% 的增长。然而,我从未想过,将其设置得更高会使我们的应用程序执行得更慢。任何想法为什么会发生这种情况?

谢谢!

编辑:

为了澄清,我使用的是 Oracle 11g R2 和 Java 6。

编辑 2:

好的,我想重申一下我的问题,因为从下面的答案来看,我没有正确表达自己:

如果我设置更高的提取大小,我的应用程序执行速度会变慢,这怎么可能?对我来说,这听起来像是在说“我们正在为您提供更快的互联网连接,即更粗的管道,但您的网页浏览会更慢。

在所有其他条件相同的情况下,正如我们在测试中所做的那样,我们非常好奇我们的应用程序在仅进行这一更改的情况下如何表现更差。

【问题讨论】:

粗略估计每行获取多长时间(如多少数据)? 我们正在谈论读取几千行数百次,例如10,000 行 * 500 次 您是否有理由不在数据库本身内部进行这种繁重的工作? 是的,因为基本上我们从两个不同的数据库中获取数据,而且它们根本无法链接。所以我们需要第三方来做比较。 这两个数据库都是Oracle实例吗?或 Oracle 和其他一些数据库。如果是这样,你怎么知道从 Oracle 中提取数据的问题? 【参考方案1】:

可能的解释:

    Java 什么都不做,而 Oracle 正在计算前 1000 行而不是前 10 行。

    Oracle 什么都不做,而 Java 正在计算最后 1000 行而不是最后 10 行。

    通信协议(例如 TCP/IP)等待很长时间,然后必须一次处理更多数据,但峰值数据传输将受到硬件限制。这被协议的开销所抵消,因此应该有最佳的提取大小,任何更少或更多的东西都会变慢;))

    如果获取过程与其他 Java 代码同步,情况会变得更糟,因此 Java 仅在处理完之前的数据后才要求更多行,而 Oracle 在此期间什么也不做。 p>

    假设有 3 个人:

    第一次将 A4 纸对折 第二个人将成堆的折叠纸从一个房间带到另一个房间 第三次从折叠的纸上剪下一些形状。

    如果第一个必须等​​到第二个返回而第二个必须等到第三个完成他们的工作,那么堆栈应该有多大?

    我猜 1000 个的堆栈不会比 10 个的堆栈好 ;))

【讨论】:

终于!这是迄今为止最清楚的解释。你的比喻很有道理。谢谢。 哦,感谢您的奖励 ;)) 只是一个旁注,我猜 Oracle 可能会预缓存接下来将要获取的数据,所以 d) 并不是真正的问题 那么这个典型的节流阀尺寸,也就是管道的实用尺寸是多少? @Sumedh 变量太多,你需要自己为你的项目做调优,en.wikipedia.org/wiki/Performance_tuning 鉴于在大多数情况下,结果的处理和提取是同步的,我很想知道,在每次提取之间,Oracle 是否正在为后续提取做准备?如果没有,那么就像第一个人只折叠第三个人要求的所需数量的文件,而当第三个人正在切割形状时,第一个人只是站着不动,什么都不做。那么除了关于 TCP/IP 节流的第 3 点之外,设置 1000 的 fetch size 不会比 10 差。我的理解是否正确?【参考方案2】:

daveslab,更多信息...

如果您的应用程序需要整个结果集来开始处理数据,更大的提取大小可以带来改进。但是,没有神奇的数字,需要检验最有利的值。

设置预取大小会影响应用程序的性能。增加预取大小将减少获取所有数据所需的往返次数,但会增加内存使用量。这将取决于查询中列的数量和大小以及预期返回的行数。它还取决于 JDBC 客户端机器的内存和 CPU 负载。最理想的是独立的客户端应用程序将不同于重负载的应用程序服务器。还应考虑网络连接的速度和延迟。

Oracle JDBC 客户端似乎预先初始化了一些内存结构以保存完整的预取大小。因此,如果您将其预取大小设置为 500,则与预取大小 = 10 相比,您分配的内存是 50 倍。这对 GC 来说是一个巨大的额外需求,尤其是如果您实际上并未读取这些行。想一想,如果您通常只获取几行,您可能会运行 GC 50x 经常超出需要;这将对您的应用程序响应能力产生重大影响。

如果可能,我建议在每个查询的基础上使用 setFetchSize。例如,如果您知道特定查询只会返回几行,则将提取大小设置为 5。如果您知道查询将返回 1000 行,则使用 100 的提取大小。

作为一种启发式方法,超过 50-100 的好处有限。

希望你明白,我正在使用谷歌翻译。

【讨论】:

【参考方案3】:

顺便说一句,至少对于 Oracle,您需要注意获取大小,因为 Oracle 驱动程序为每行占用的最大可能大小留出了一个数组,而不是实际数据大小。因此,如果您有一个胖表,您的内存占用可能会受到影响。

看看这里 - http://www.oracle.com/technetwork/database/enterprise-edition/memory.pdf

在 Oracle 中,您可以找出 user_tab_columns 元数据表 (data_length) 中的列占用的最大空间。它可用于确定提取大小。

在粗略的测试中,我发现 4 * 1024 * 1024 / sum(data_length for all columns of your table) 是一个合理的获取大小。

【讨论】:

感谢这个链接:oracle.com/technetwork/database/enterprise-edition/… 完美地解释了 jdbc 内存和获取大小的东西是如何工作的。 另请参阅***.com/q/28161049/32453 以获取有关如何不需要这么多 RAM 但仍使用预取的提示列表 @techcraver 您的 pdf 链接错误。应该是oracle.com/technetwork/database/enterprise-edition/memory.pdf。谢谢!!【参考方案4】:

与所有内容一样,没有FAST=TRUE 设置。虽然 10 的 JDBC 默认提取大小不适合您的情况,但对于“典型”OLTP 应用程序来说是可以的,而且看起来对您的情况也没有那么不好。显然,较大的 fetch 大小也不适合您的情况。但同样,一次做 1000 次也没有那么糟糕。

您没有提到的另一个因素是被拉出的行的WIDE。考虑您通过网络从数据库服务器拉取到应用服务器的数据块是sum(WIDTH*ROWS)。如果您的行是 5000 字节,并且您一次提取 1000 个字节,那么每次提取将带来 5 MB 的数据。在另一种情况下,也许您的行“瘦”只有 100 个字节。然后获取其中的 1000 个只是在周围穿梭 100K 件。

因为只有您可以知道返回的数据是什么样子,所以建议为“一般”情况设置系统范围的提取大小,然后根据需要单独调整古怪的查询。

总的来说,我也发现 100 是大型数据处理的更好设置。这不是建议,而是转述观察。

【讨论】:

我同意大型数据处理的 fetch size ~= 100。 记得用不同的数字来配置文件——对我们来说,我们得到了改进,一直到 3200-4000,所以试试吧!【参考方案5】:

正如 Adam H. 所说的那样 - 没有适用于每种场景的通用设置。 Oracle 需要时间来获取行,因此它在服务器端等待行,然后将其发送到客户端之前,可能已经在您的应用程序中花费了时间,如果预取阈值设置得较低,那么性能会受到影响。

据我回忆,Oracle 还使用客户端缓存来提供可滚动游标。至少从记忆的角度来看,将光标设置为仅向前可能会有所帮助。至少它曾经在旧版本的 JDBC 驱动程序中有所帮助,也许从那以后行为发生了变化。

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY);

【讨论】:

【参考方案6】:

The correct method 是使用 setFetchSize。

默认情况下,当 Oracle JDBC 运行查询时,它会检索结果集 从数据库游标一次 10 行。这是默认设置 Oracle 行提取大小值。您可以更改行数 通过更改行在每次访问数据库游标时检索 获取大小值。

标准 JDBC 还允许您指定获取的行数 每次数据库往返一次查询,并引用此编号 作为获取大小。在 Oracle JDBC 中,使用行预取值 作为语句对象中的默认提取大小。设置抓取 size 覆盖行预取设置并影响后续查询 遍历那个语句对象。

获取大小也用于结果集中。语句对象运行时 一个查询,将语句对象的获取大小传递给 查询产生的结果集对象。但是,您也可以设置 获取结果集对象中的大小以覆盖语句获取 传递给它的大小。

【讨论】:

对于有意义的单个查询,但设置系统属性应该只是覆盖默认值,不是吗? 您可以设置系统属性,或按连接配置:docs.oracle.com/cd/A97335_02/apps.102/a83724/…

以上是关于将 Oracle 的行大小设置得更高会使我的应用程序变慢?的主要内容,如果未能解决你的问题,请参考以下文章

输入 UISearchBar 会使我的应用程序崩溃

使用 CGContext 调整 UIImage 的大小会使我的图像变软,像素密度错误

将 wordexp 的输出提供给 getopt_long 会使我的 linux cli 应用程序崩溃

更改为横向会使我的 Android 应用程序崩溃

激活 iPhone 相机操作会使我的应用程序崩溃 [重复]

编辑模式下的 UITableView - 按 Delete 会使我的应用程序崩溃