mysql的ps.setmaxrows,SQL LIMIT与JDBC语句setMaxRows。哪一个更好?

I want to select the Top 10 records for a given query. So, I can use one of the following options:

Using LIMIT and OFFSET in the SQL query

What are the advantages and disadvantages of these two options?

解决方案

SQL-level LIMIT

To restrict the SQL query result set size, you can use the SQL:008 syntax:

SELECT title

FROM post

ORDER BY created_on DESC

OFFSET 50 ROWS

FETCH NEXT 50 ROWS ONLY

which works on Oracle 12, SQL Server 2012, or PostgreSQL 8.4 or newer versions.

For MySQL, you can use the LIMIT and OFFSET clauses:

SELECT title

FROM post

ORDER BY created_on DESC

LIMIT 50

OFFSET 50

The advantage of using the SQL-level pagination is that the database execution plan can use this information.

So, if we have an index on the created_on column:

CREATE INDEX idx_post_created_on ON post (created_on DESC)

And we execute the following query that uses the LIMIT clause:

EXPLAIN ANALYZE

SELECT title

FROM post

ORDER BY created_on DESC

LIMIT 50

We can see that the database engine uses the index since the optimizer knows that only 50 records are to be fetched:

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

JDBC Statement maxRows

If the limit is exceeded, the excess rows are silently dropped.

That's not very reassuring!

So, if we execute the following query on 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++;

}

}

We get the following execution plan in the PostgreSQL log:

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

Because the database optimizer has no idea that we need to fetch only 50 records, it assumes that all 5000 rows need to be scanned. If a query needs to fetch a large number of records, the cost of a full-table scan is actually lower than if an index is used, hence the execution plan will not use the index at all.

I ran this test on Oracle, SQL Server, PostgreSQL, and MySQL, and it looks like the Oracle and PostgreSQL optimizers don't use the maxRows setting when generating the execution plan.

However, on SQL Server and MySQL, the maxRows JDBC setting is taken into consideration, and the execution plan is equivalent to an SQL query that uses TOP or LIMIT. You can run the tests for yourself, as they are available in my High-Performance Java Persistence GitHub repository.

Conclusion

Although it looks like the setMaxRows is a portable solution to limit the size of the ResultSet, the SQL-level pagination is much more efficient if the database server optimizer doesn't use the JDBC maxRows property.

For more details about how you can write a Top-N SQL query with Oracle, SQL Server, PostgreSQL, and MySQL, check out this article.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值