Ron*_*yen 5 java postgresql jdbc
我想选择前10条记录,我可以使用以下之一:
我的问题是:它们之间的优点和缺点是什么?
Vla*_*cea 20
要限制 SQL 查询结果集大小,可以使用 SQL:008 语法:
SELECT title
FROM post
ORDER BY created_on DESC
OFFSET 50 ROWS
FETCH NEXT 50 ROWS ONLY
Run Code Online (Sandbox Code Playgroud)
适用于 Oracle 12、SQL Server 2012 或 PostgreSQL 8.4 或更新版本。
对于 MySQL,您可以使用 LIMIT 和 OFFSET 子句:
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
OFFSET 50
Run Code Online (Sandbox Code Playgroud)
使用 SQL 级分页的好处是数据库执行计划可以使用这些信息。
所以,如果我们在created_on列上有一个索引:
CREATE INDEX idx_post_created_on ON post (created_on DESC)
Run Code Online (Sandbox Code Playgroud)
我们执行以下使用该LIMIT子句的查询:
EXPLAIN ANALYZE
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
Run Code Online (Sandbox Code Playgroud)
我们可以看到数据库引擎使用索引,因为优化器知道只需要提取 50 条记录:
Execution plan:
Limit (cost=0.28..25.35 rows=50 width=564)
(actual time=0.038..0.051 rows=50 loops=1)
-> Index Scan using idx_post_created_on on post p
(cost=0.28..260.04 rows=518 width=564)
(actual time=0.037..0.049 rows=50 loops=1)
Planning time: 1.511 ms
Execution time: 0.148 ms
Run Code Online (Sandbox Code Playgroud)
如果超出限制,多余的行将被静默删除。
这不是很让人放心!
因此,如果我们在 PostgreSQL 上执行以下查询:
try (PreparedStatement statement = connection
.prepareStatement("""
SELECT title
FROM post
ORDER BY created_on DESC
""")
) {
statement.setMaxRows(50);
ResultSet resultSet = statement.executeQuery();
int count = 0;
while (resultSet.next()) {
String title = resultSet.getString(1);
count++;
}
}
Run Code Online (Sandbox Code Playgroud)
我们在 PostgreSQL 日志中得到如下执行计划:
Execution plan:
Sort (cost=65.53..66.83 rows=518 width=564)
(actual time=4.339..5.473 rows=5000 loops=1)
Sort Key: created_on DESC
Sort Method: quicksort Memory: 896kB
-> Seq Scan on post p (cost=0.00..42.18 rows=518 width=564)
(actual time=0.041..1.833 rows=5000 loops=1)
Planning time: 1.840 ms
Execution time: 6.611 ms
Run Code Online (Sandbox Code Playgroud)
因为数据库优化器不知道我们只需要获取 50 条记录,所以它假设需要扫描所有 5000 行。如果查询需要获取大量记录,全表扫描的成本实际上比使用索引要低,因此执行计划根本不会使用索引。
我在 Oracle、SQL Server、PostgreSQL 和 MySQL 上运行了这个测试,看起来 Oracle 和 PostgreSQL 优化器
maxRows在生成执行计划时不使用该设置。但是,在 SQL Server 和 MySQL 上,
maxRows考虑了JDBC 设置,执行计划相当于使用TOP或的 SQL 查询LIMIT。您可以自己运行测试,因为它们在我的高性能 Java 持久性 GitHub 存储库 中可用。
尽管看起来setMaxRows是限制 大小的可移植解决方案ResultSet,但如果数据库服务器优化器不使用 JDBCmaxRows属性,则 SQL 级别的分页效率会更高。
setmaxrows的优点是您可以创建在Postgres,Oracle,Mysql等中有效的通用语句。由于Oracle使用rownum语法,因此postgres-limit,msqsql-top
在速度上似乎没有什么区别。
对于大多数情况,您希望使用该LIMIT子句,但最终两者都会实现您想要的。这个答案针对的是 JDBC 和 PostgreSQL,但也适用于使用类似模型的其他语言和数据库。
JDBC 文档Statement.setMaxRows说
如果超出限制,多余的行将被静默删除。
即数据库服务器可能返回更多行,但客户端将忽略它们。PostgreSQL JDBC 驱动程序对客户端和服务器端都有限制。对于客户端,请查看maxRows中AbstractJdbc2ResultSet的用法。对于服务器端,请查看maxRowsinQueryExecutorImpl。
服务器端,PostgreSQLLIMIT文档说:
查询优化器在生成查询计划时考虑 LIMIT
因此,只要查询合理,它就会仅加载完成查询所需的数据。
| 归档时间: |
|
| 查看次数: |
7383 次 |
| 最近记录: |