【问题标题】:Fetch Multiple blobs in Oracle在 Oracle 中获取多个 blob
【发布时间】:2013-12-11 05:11:42
【问题描述】:

我们将数据以序列化的形式存储在 Oracle 表中。保存序列化数据的列是 BLOB 类型。我们确实有一个存储过程来查询表并将结果作为 sys_refcursor 返回。存储过程接受逗号分隔形式的键列表,用于获取 Blob。

环境 - JRE 1.6 甲骨文11g

问题:当应用程序请求 8 或 10 行的数据时,我们希望存储过程在单个 db 往返中返回所有带有二进制数据的结果行。这可能吗?或者以最少的数据库往返获取结果的最佳方法是什么。

(我们已将 fetchRowsize 设置为 10,以便获取多行。我们还将 setLOBPrefetchSize 设置为足够大的值(3 Meg)。但是这些似乎没有区别。resultSet.getBytes()花费大量时间表明数据是按请求获取的)

我错过了什么?我们是否有任何跟踪来启用/检查下面发生的事情?

【问题讨论】:

    标签: java oracle jdbc oracle11g


    【解决方案1】:

    BLOB 有意触发某些特定行为,因为它们可能非常大(取决于块大小,但最大大小至少为 8 TB)。驱动程序并不总是事先知道将传输多少数据,因此驱动程序默认选择安全路线。

    我知道您希望它在一次往返中完成,可能是因为您的网络延迟?如果不是,请说明。

    我们开发的标准软件包也遇到了同样的问题,客户端在连接设置时会在全球范围内检索大量数据。我们已解决如下:

    1. 最初,我们使用了一个存储过程,该过程采用最后检索到的数据行的哈希值作为参数。存储过程检查当前数据行的哈希。如果没有不同,它只返回一个标题。如果不同,它会将所有内容放在一个大块中并将其发送回去。通过这种方式,它避免了在全球范围内传输大量信息,因为高网络延迟通常伴随着低带宽。此外,往返次数也减少了。
    2. 在过去的两年中,我们在中间插入了我们公司的不同产品(网络服务提供商)。它自己进行压缩和重复数据删除,进一步减少了带宽需求。此外,它仅在 Web 服务和 Oracle RDBMS 之间使用 SQL*Net。 Web 服务使用 bson(二进制格式的 json)进行通信。

    我建议只需从存储过程中返回一个包含所有内容的 LOB 即可。甚至可以压缩它或使用客户端的缓存。

    上述选项 2 需要花费更多的精力来介绍。

    【讨论】:

    • 延迟是主要问题。我们的网络有大约 20-30 毫秒的 RTT。如果我们要获取多个实体,这将使我们保持连接更长时间(我们希望避免这种情况)。我们倾向于选项 1,但需要更多地了解如何将 BLOB 拆分回客户端代码中。 (我看到我们可以使用 dbms_lob.Append 函数将 LOB 附加到服务器中)。
    • 您是否使用单独的 LOB 长度进行拆分?或任何其他更好的选择?
    • 在第 1 步中,我们使用类似于“首先告诉我字节如何跟随,然后是内容”的方式进行分隔。类似于许多运行时环境中的 String 环境(不是带有尾随 \0 的 C)。在第 2 步中,我们使用 bson 包装(序列化)它。所以二进制格式为 [ [ [ field 1 name ], [field 2 name] ], [ [PAYLOAD 1 ROW 1], [PAYLOAD 2 ROW 1] ], [ [PAYLOAD 3 of ROW 2], ...] ]
    【解决方案2】:

    如果您碰巧使用 Oracle 的瘦 JDBC 驱动程序,您可能想尝试将连接属性 useFetchSizeWithLongColumn 设置为 true,请参阅 http://download.oracle.com/otn_hosted_doc/jdeveloper/905/jdbc-javadoc/index.html?oracle/jdbc/OracleDriver.html。但是,正如属性名称所示,它适用于 LONG 列,并且可能对 BLOB 列没有任何影响。 (不幸的是,我自己无法在这里尝试。但是,http://ora-jdbc-source.googlecode.com/svn/trunk/OracleJDBC/src/oracle/jdbc/driver/OracleResultSetImpl.java 下的源代码似乎与 useFetchSizeWithLongColumn 没有区分 LONG/LOB,只是“重新打开流”。)

    有关验证/跟踪,请参见:http://steveracanovic.blogspot.de/2009/08/using-usefetchsizewithlongcolumn-and.html 中的示例代码

    如果连接属性不适用于 BLOB,您可以尝试返回 LONG。但是,似乎没有一种从 BLOB 转换为 LONG 的好方法。以下讨论(参见答案)提到了在 PL/SQL 中使用 RAW 变量的方法:http://oracle.mscer.com/q_oracle_41102.html。正如你提到的使用存储过程,你可能想试试这个。

    (请注意,设置连接属性意味着预取的 LONG 数据可能会消耗大量内存。)

    (再次抱歉,我不能自己尝试这种方法,也无法提供详细信息,因为我这里没有 Oracle 数据库。但是在过去两个小时内没有人想出答案......)

    【讨论】:

      猜你喜欢
      • 2018-12-24
      • 2015-01-29
      • 2021-12-01
      • 2021-01-02
      • 2021-11-29
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多