【问题标题】:What is the best way to iterate over a large result set in JDBC/iBatis 3?在 JDBC/iBatis 3 中迭代大型结果集的最佳方法是什么?
【发布时间】:2010-04-27 10:28:22
【问题描述】:

我们正在尝试迭代数据库中的大量行并将它们转换为对象。行为如下:

  • 结果将按序列ID排序,当序列ID改变时将创建一个新对象。创建的对象将被发送到外部服务,有时必须等待再发送另一个(这意味着不会立即使用下一组数据)
  • 我们已经在 iBatis 3 中投入了代码,因此 iBatis 解决方案将是我们的最佳方法(我们尝试使用 RowBounds,但还没有看到它是如何进行底层迭代的)。
  • 我们希望在最小化内存使用和减少 DB 访问次数之间取得平衡。
  • 我们也对纯 JDBC 方法持开放态度,但我们希望该解决方案适用于不同的数据库。

更新 1

  • 我们需要尽可能少地调用 DB(1 次调用是理想的情况),同时还要防止应用程序使用过多的内存。对于此类问题,是否还有其他解决方案,可能是纯 JDBC 或任何其他技术?

更新 2

  • 查询将由后端驱动,并且在给定时间只会执行 1 个实例。

感谢并希望听到您对此的见解。

【问题讨论】:

    标签: java jdbc ibatis


    【解决方案1】:

    我们需要尽可能少地调用 DB(1 次调用是理想的场景),同时还要防止应用程序使用过多的内存。对于此类问题,是否有其他解决方案,可能是纯 JDBC 或任何其他技术?

    您真的不应该担心数据库调用的数量。只需准确查询最终用户需要立即查看的数据。它不能更有效地完成。 Google 也不会查询整个数据库以仅显示前 10 个。不,它会查询这 10 个以进行显示,不多也不少。这比将整个数据库拖到/复制到应用程序的内存中并处理它要快得多、效率高得多。充分利用 RDBMS 的力量。这就是它的发明/目的。

    【讨论】:

    • 感谢 BalusC。抱歉,但我忘了提到这不是用户驱动的查询,而是由后端触发的查询。不知道老板为什么想要一个数据库调用,我提到用这种方法可能很难平衡内存使用,但他建议继续尝试,这就是为什么我仍在寻找其他替代方案。
    • +1 BalusC 是对的,一般来说(我也怀疑特别是)
    • @paul: 好吧,如果老板这么说的话...... :/ 和他谈谈。说服他更多。
    【解决方案2】:

    看来您需要某种分页。 iBatis 通过查询中的标准 LIMIT/OFFSET 参数(以及 iBatis 3 中的 RowBounds)来做到这一点。

    但似乎(如果我没听错的话)您也在使用 iBatis 的 GROUP BY 功能,因此选择返回 N 条记录并带有 N1 个不同的“idx”字段会导致每个创建 N1 个“父”对象一个有几个子对象(总共创建了 N 个子对象)。或类似的东西。

    不幸的是(并且可以理解)do not mix well

    我在这里没有看到任何灵丹妙药,可以想到很多方法,每种方法都有其缺点 - 没有更多信息很难评估。

    如果主要对象是“大”(许多记录)并且每个对象都将被单独处理(访问远程服务器),您甚至可能想要进行临时分页,每页有一个对象,记住内部是先前读取的 id(类似于 SELECT ... FROM ... WHERE id = (SELECT MIN(id) FROM .... WHERE id > #lastid# ))

    【讨论】:

    • 1.我有一种感觉 iBatis 正在使用 LIMIT/OFFSET,我想这意味着它需要为每个页面访问数据库,对吧? 2. 我们在 Java 端进行分组,所以不需要在查询中使用 group by 关键字,我们只需要将结果按 id 排序,这样我们就可以在处理下一个对象之前完成创建具有相同 id 子项的对象对象。 3. 您的临时分页听起来像是 RowBounds 方法的一个很好的替代方案。这样我们就可以保证只检索下一个对象。我会试一试并检查性能。感谢 leonbloy 的帮助!
    • 我添加了一个新要求,即尽可能少地进行数据库往返。希望您也可以对更新发表评论。谢谢!
    • 我坚持在一个 DB 查询中执行此操作,请查看 RowHandler 或 ResultHandler -(或者,更奇特的是,返回 ResultSet/Cursor - 或恢复为普通 JDBC)。但这只有在每个“对象”远程执行的操作都应该给出响应(快速 - 不依赖于某些人工交互)并且您可以相信循环将完成时才合理。
    • ResultSet/Cursor 方法是我相信我的老板正在寻找的。我刚刚看到 PostgreSQL 的 setFetchSize 教程,使用 ResultSet.TYPE_FORWARD_ONLY 和 setAutocommit(false) 来启用此行为。不幸的是,我现在正在使用 MySQL 进行尝试,但它看起来不受支持。你知道哪些数据库有这个吗?谢谢。
    • 好的,我将 ?useCursorFetch=true 添加到 MySQL 的驱动程序 URL 中,内存使用量从 364651264 下降到 4160608。我将尝试检查 setFetchSize 在 DB2 和 Oracle 中是否支持。谢谢。
    猜你喜欢
    • 2023-03-09
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多