代码之家  ›  专栏  ›  技术社区  ›  yawn

Oracle CLOB性能

  •  8
  • yawn  · 技术社区  · 15 年前

    我正在使用JDBC(使用最新的驱动程序和UCP作为数据源)对Oracle10g运行查询,以检索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 回复  |  直到 10 年前
        1
  •  6
  •   TrojanName    11 年前

    结果集的总大小以10000为单位-在整个检索范围内测量初始成本

    查询中是否有订单依据?如果必须对10公里的行进行排序,那就相当多了。

    此外,检索pk与检索整个CLOB相比,是不公平的测试。Oracle将表行存储在一个块中,其中可能有许多行,但每个CLOB(如果是>4K)都将以脱机方式存储,每个CLOB都存储在一系列块中。因此,扫描pk的列表将会很快。另外,可能在pk上有一个索引,所以Oracle可以快速扫描索引块,甚至不能访问表。

    4秒看起来有点高,但是它是2MB,需要从磁盘读取并通过网络传输到Java程序。网络可能是个问题。如果您对会话执行SQL跟踪,它将精确地指示您所花费的时间(磁盘读取或网络)。

        2
  •  5
  •   Oscar Chan    15 年前

    我过去使用OracleLob类型数据存储大数据的经验并不好。当它低于4K时就可以了,因为它像varchar2一样存储在本地。一旦超过4K,性能就会下降。也许,自从我几年前最后一次尝试后,情况可能有所改善,但下面是我在过去发现的一些东西,供您参考:

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

    • 业务线数据将与有限的SGA竞争 如果Oracle 决定缓存它。因为CLOB数据 大将军,所以可能会推其他人 数据
    • 如果 Oracle决定不缓存它,并且 将数据传输到客户端。
    • 碎片可能是某种东西 你还没有遇到。您将看到您的应用程序是否删除了LOB,Oracle是否尝试重用LOB。我不知道Oracle是否支持对lob磁盘进行联机碎片整理(它们支持索引,但在我们之前尝试时需要很长时间)。

    你提到平均每100只龙虾吃4只,每只龙虾吃40毫秒。记住,每个LOB都需要通过单独的LOB定位器进行检索(默认情况下,它不在结果集中)。对于每个业务线来说,这是一次额外的往返行程,我想(我不完全确定这一点,因为这是一段时间以前的事情),如果是这样的话,我想每一次往返都会有至少5毫秒的连续时间,对吗?如果是这样,那么您的性能首先会受到连续的LOB提取的限制。您应该能够通过跟踪SQL执行与LOB内容获取所花费的时间来验证这一点。或者,您可以通过排除前文答案建议的lob列来验证这一点,该列应该告诉您它是否与lob相关。

    祝你好运

        3
  •  4
  •   cheffe    10 年前

    我遇到了类似的问题,发现JDBCLob在访问Lob时发出网络调用。

    从Oracle 11.2g JDBC驱动程序开始,您可以使用预取。 这使访问速度加快了10倍…

    statement1.setFetchSize(1000);
    if (statement1 instanceof OracleStatement) {
        ((OracleStatement) statement1).setLobPrefetchSize(250000);
    }
    
        4
  •  2
  •   yawn    15 年前

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

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

    我现在选择了一个额外的往返数据库,在其中我将把CLOB预处理成一个大小优化的二进制原始文件。在以前的部署中,这一直是一个非常快速的选项,可能值得维护离线计算缓存。在有人想出更好的主意之前,缓存将被禁用,并使用持久性进程和AQ进行更新。