Backend Development 9 min read

Understanding and Optimizing MyBatis PageHelper Pagination Performance

This article analyzes the performance bottlenecks of PageHelper's pagination in MyBatis, demonstrates how large offsets degrade MySQL query speed, and presents a more efficient sub‑query join solution along with suggestions for refactoring the interceptor to improve backend pagination efficiency.

Top Architect
Top Architect
Top Architect
Understanding and Optimizing MyBatis PageHelper Pagination Performance

The project originally used PageHelper for pagination, which worked fine with small data volumes but showed severe performance degradation as the dataset grew to hundreds of thousands or millions of rows. By tracing the PageHelper source code, the article reveals how pagination is implemented via LIMIT clauses appended to the original SQL.

Key code snippets illustrate the creation of a Page object, the interception process, and the generation of the final paginated SQL:

public ResultContent select(Integer id) {
    Page
blogPage = PageHelper.startPage(1,3).doSelectPage(() -> testDao.select(id));
    List
test = (List
)blogPage.getResult();
    return new ResultContent(0, "success", test);
}
public static
Page
startPage(int pageNum, int pageSize) {
    return startPage(pageNum, pageSize, DEFAULT_COUNT);
}

Further inspection shows how MyBatis' MapperProxy and PageInterceptor invoke the original SQL, construct a CacheKey , and eventually call ExecutorUtil.pageQuery to apply the pagination logic.

The article then demonstrates MySQL's LIMIT offset, count performance issue: small offsets ( LIMIT 1,10 ) execute quickly, while large offsets ( LIMIT 100000,10 ) cause seconds of delay. To mitigate this, a sub‑query that first selects primary keys with the desired offset and then joins back to the full table is proposed, reducing the execution time from several seconds to under one second.

SELECT a.* FROM USER a
INNER JOIN (
    SELECT id FROM USER WHERE age = 10 LIMIT 100000,10
) b ON a.id = b.id;

The solution relies on indexing the WHERE condition and leveraging the primary‑key index to avoid full table scans. Finally, the article suggests that optimizing PageHelper itself would require refactoring the SQL‑building part of its interceptor, and provides the GitHub repository link for reference.

GitHub: https://github.com/pagehelper/Mybatis-PageHelper/

BackendJavaPerformanceSQLMyBatispaginationPageHelper
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.