2012-04-16 49 views
6

我正在尝试使用JDBC编写一个数据库独立应用程序。我现在需要一种方法从某个表中获取前N个条目。我看到JDBC中有一个setMaxRows方法,但我不习惯使用它,因为我害怕数据库将推出所有结果,只有JDBC驱动程序会减少结果。如果我需要排在十亿行的表中前5名的结果,这将打破我的脖子(该表有一个可用的索引)。JDBC setMaxRows数据库使用情况

编写特殊的SQL语句为每一种数据库是不是很漂亮,但会让数据库做聪明的查询计划,并停止获取超过必要的结果。

我可以依靠setMaxRows告诉数据库到不行到多少?

我猜我不能依靠在希望的方式这个工作的最坏情况。我最感兴趣的是Postgres 9.1和Oracle 11.2,所以如果有人对这些数据库有经验,请继续前进。

+2

好问题。 javadoc说:“设置由Statement对象生成的任何ResultSet对象可以包含的最大行数限制为给定数量,如果超出限制,超出的行将自动丢弃。”我读到它的方式意味着JDBC驱动程序可以完成这项工作。我怀疑它的JDBC实现依赖。 – 2012-04-16 14:05:41

回答

3

将让数据库执行巧妙的查询计划并停止获取比必要更多的 结果。

如果使用

PostgreSQL

SELECT * FROM tbl ORDER BY col1 LIMIT 10; -- slow without index 

或者:

SELECT * FROM tbl LIMIT 10;    -- fast even without index 

Oracle

SELECT * 
FROM (SELECT * FROM tbl ORDER BY col1 DESC) 
WHERE ROWNUM < 10; 

..那么只有10行将是返回。但是,如果你挑选前10名之前的行进行排序,所有基本上符合条件的行会阅读能够对其进行排序之前。

匹配索引可以防止这种开销!


如果您不确定JDBC实际发送到数据库服务器的数据,请运行测试并让数据库引擎记录收到的语句。在PostgreSQL可以set in postgresql.conf

log_statement = all 

(和重装)登录发送到服务器的所有语句。测试结束后务必重置该设置,否则日志文件可能会变得很大。

1

这可能/可能会杀死你行的十亿(S)的事情是在你的查询(很有可能)ORDER BY条款。如果这个订单不能使用索引建立,那么。 。 。它会打破你的脖子:)

我不会依赖于这里的jdbc驱动程序。正如之前的评论所暗示的,它不清楚它究竟做了什么(看着不同的rdbms)。

如果您对您的查询的速度而言,你可以使用LIMIT条款也是如此。如果您使用LIMIT,则至少可以确保它已传递到数据库服务器。

编辑:对不起,我不知道Oracle不支持LIMIT

1

在直接回答您关于PostgreSQL 9.1的问题时:是的,JDBC驱动程序会告诉服务器停止生成超出您设置的行。

正如其他人所指出的,根据索引和所选计划,服务器可能会扫描大量的行以找到您想要的五个行。正确的服务器配置可以帮助准确地模拟成本以防止出现这种情况,但是如果价值分布不寻常,则可能需要引入和优化障碍(如与CTE一样)来强制规划者制定一个良好的计划。