我正在使用 JDBC 对 Oracle 10g 运行查询(使用最新的驱动程序和 UCP 作为数据源),以检索 CLOB(平均)。20k 个字符)。然而,性能似乎相当糟糕:批量检索100个LOB平均耗时4秒。从我的观察来看,该操作既不是 I/O,也不是 CPU,也不是网络限制。

我的测试设置如下所示:

PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource();
dataSource.setConnectionFactoryClassName("...");
dataSource.setConnectionPoolName("...");
dataSource.setURL("...");
dataSource.setUser("...");
dataSource.setPassword("...");

dataSource.setConnectionProperty("defaultRowPrefetch", "1000");
dataSource.setConnectionProperty("defaultLobPrefetchSize", "500000");

final LobHandler handler = new OracleLobHandler();
JdbcTemplate j = new JdbcTemplate(dataSource);

j.query("SELECT bigClob FROM ...",

        new RowCallbackHandler() {

            public void processRow(final ResultSet rs) throws SQLException {

                String result = handler.getClobAsString(rs, "bigClob");

            }

        });

}

我尝试了获取大小,但没有成功。难道我做错了什么?使用 JDBC 时有没有办法加快 CLOB 检索速度?

有帮助吗?

解决方案 4

感谢所有有用的建议。尽管被标记为问题的答案,但我的答案是似乎没有好的解决方案。我尝试使用并行语句、不同的存储特性、预排序的温度。桌子和其他东西。该行动似乎不受任何通过痕迹或解释计划可见的特征的约束。当涉及 CLOB 时,甚至查询并行性似乎也很粗略。

毫无疑问,除了 atm 之外,在 11g 环境中还有更好的选择来处理大型 CLOB(尤其是压缩)。我被10g困住了。

我现在选择对数据库进行额外的往返,在其中将 CLOB 预处理为大小优化的二进制 RAW。在以前的部署中,这一直是一个非常快的选项,并且可能值得维护离线计算缓存。缓存将失效并使用持久进程和 AQ 进行更新,直到有人提出更好的想法。

其他提示

我过去使用oracle LOB类型数据存储大数据的经验并不好。当它低于 4k 时就可以了,因为它像 varchar2 一样存储在本地。一旦超过 4k,您就会开始看到性能下降。也许,自从我几年前上次尝试以来,情况可能有所改善,但以下是我过去发现的内容供您参考:

由于客户端需要通过 Oracle 服务器获取 LOB,您可能会考虑以下有趣的情况。

  • 如果Oracle决定缓存,LOB数据将与其他数据类型竞争有限的SGA缓存。由于clob数据一般很大,因此它可能会推动其他数据
  • LOB数据会使磁盘差阅读,如果Oracle决定不缓存,则将数据流式传输给客户端。
  • 分裂可能是您尚未遇到的东西。您将看到您的应用程序是否删除了 lob,并且 Oracle 尝试重用该 lob。我不知道oracle是否支持在线对lob进行磁盘碎片整理(他们有索引,但我们之前尝试过需要很长时间)。

您提到平均 20k 的 100 个 lob 需要 4 秒,因此每个 lob 需要 40 毫秒。请记住,每个 lob 都需要通过单独的 Lob 定位器检索(默认情况下它不在结果集中)。我假设这是每个 lob 的额外往返(我对此不是 100% 确定,因为这是不久前的事)如果是这样的话,我假设按顺序每个往返至少有 5 毫秒的额外时间, 正确的?如果是这样,您的性能首先会受到顺序 lob 提取的限制。您应该能够通过跟踪 sql 执行与 lob 内容获取所花费的时间来验证这一点。或者,您可以按照帖子中先前答案的建议排除 lob 列来验证这一点,这应该告诉您它是否与 lob 相关。

祝你好运

  

结果集的总大小是在数万 - 在整个检索的跨度测量的初始成本

有一个ORDER BY查询? 10K行是相当多的,如果它已进行排序。

另外,检索的PK是不公平的测试与检索整个CLOB。甲骨文存储与可能在一个块中的许多,但每一个的CLOB的表中的行(如果它们是> 4K)将被存储脱节,各自在一系列块。因此扫描PK的名单将是快。此外,有可能是在PK的索引,所以Oracle可以直接快速扫描索引块,甚至不能访问该表。

4秒时确实显得有点高,但它是2MB的需要从磁盘读取的可能,并通过网络传输到你的Java程序。网络可能是一个问题。如果执行的会话的SQL跟踪它将指向你在时间被消耗的准确位置(磁盘读取或网络)。

我也有类似的问题,并发现accessin的高吊球时,JDBC的LOB进行网络通话。

作为Oracle11.2克JDBC驱动就可以使用预取。 通过10倍这加快了访问...

statement1.setFetchSize(1000);
if (statement1 instanceof OracleStatement) {
    ((OracleStatement) statement1).setLobPrefetchSize(250000);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top