我应该在啥时候指定 setFetchSize()?
Posted
技术标签:
【中文标题】我应该在啥时候指定 setFetchSize()?【英文标题】:What and when should I specify setFetchSize()?我应该在什么时候指定 setFetchSize()? 【发布时间】:2014-01-20 21:44:51 【问题描述】:我看到很多 JDBC/mysql 的“最佳实践”指南告诉我指定 setFetchSize()。
但是,我不知道何时指定,以及指定什么(语句、结果集)。
Statement.setFetchSize() or PreparedStatement.setFetchSize()
ResultSet.setFetchSize()
-
在这两个中,我应该指定什么?
来自javadoc 和oracle documentation,这就是我对“何时”感到困惑的地方
Java 文档
默认值由创建结果集的 Statement 对象设置。提取大小可以随时更改。
Oracle 文档
生成结果集后对语句对象的提取大小所做的更改不会影响该结果集。
如果我错了,请纠正我。这是否意味着setFetchSize只有在查询执行之前才有效?(因此,ResultSet上的setFetchSize是没有用的?但恰好“获取大小可能随时更改”?)
【问题讨论】:
第二个链接是针对 Oracle JDBC 驱动程序(即针对 Oracle database),而不是“通用”JDBC 文档 - 特别是 not mysql。您应该查看 MySQL JDBC 手册以获取有关该实现的详细信息。 @a_horse_with_no_name 感谢您指出这一点。很明显,我应该先检查一下…… docs.oracle.com/cd/A87860_01/doc/java.817/a83724/resltse5.htm 【参考方案1】:您应该阅读关于结果集的官方文档中的page。它说
默认情况下,ResultSet 被完全检索并存储在内存中。在大多数情况下这是最有效的操作方式,并且由于 MySQL 网络协议的设计更容易实现。如果您正在使用具有大量行或大值的 ResultSet,并且无法在 JVM 中为所需内存分配堆空间,您可以告诉驱动程序一次将结果流回一行。
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
只进、只读结果集与 Integer.MIN_VALUE 提取大小的组合用作驱动程序逐行流式传输结果集的信号。在此之后,将逐行检索使用该语句创建的任何结果集。
实际上,仅设置 fetchSize 对 connector-j 实现没有影响。
【讨论】:
这仅适用于 MySQL,大多数其他数据库和 JDBC 驱动程序的表现都比这更好。 没错,但是问题至少部分是关于 MySQL 的。 因为这个问题也提到了 Oracle 文档,所以我把它当作一个一般的 JDBC 问题;这是我对 MySQL 连接器/J 实现的不满之一...... :) 在浪费了一些时间尝试替代方案之后,我可以确认 Connector/J 确实只支持返回整个结果集,或者一次流式传输它们。我希望返回 10,000 个批次,但源代码专门检查 Integer.MIN_VALUE 并在指定任何其他值时返回所有内容。对于使用 JDBI (jdbi.org) 的任何人,将获取大小添加到查询中就足够了,因为其他标志已经处于正确的值:handle.createQuery(sql).setFetchSize(Integer.MIN_VALUE).map()/fold( ) 等 这(不再)是真的;在设置 JDBC 选项useServerFetch
时,MySQL 实际上支持任何正获取大小。但是,有一些警告;看看我对这个类似问题的回答:***.com/a/36986532/1016939【参考方案2】:
找到一篇很好的文章,其中包含您的问题的 示例:
https://www.baeldung.com/jdbc-resultset
7.1。在语句上使用 Fetch Size 7.2.在 ResultSet 上使用 Fetch Size
【讨论】:
以上是关于我应该在啥时候指定 setFetchSize()?的主要内容,如果未能解决你的问题,请参考以下文章
UIViewController 的 viewDidAppear/viewDidDisappear:应该在啥时候调用这些方法?