分页查询的基本原理

在MySQL中通过LIMITOFFSET实现分页。核心语法:

SELECT * FROM large_table 
LIMIT pageSize OFFSET (pageNum - 1) * pageSize

优化查询性能的关键方法

使用覆盖索引 确保查询只通过索引获取数据,避免回表操作:

SELECT id FROM large_table 
WHERE condition 
LIMIT 1000 OFFSET 20000

延迟关联技术 先通过索引定位主键,再关联原表:

SELECT t.* FROM large_table t
INNER JOIN (
    SELECT id FROM large_table
    WHERE condition
    LIMIT 1000 OFFSET 20000
) tmp ON t.id = tmp.id

Java实现分页的最佳实践

MyBatis分页插件配置 添加PageHelper依赖后示例代码:

PageHelper.startPage(pageNum, pageSize);
List<Data> list = dataMapper.selectLargeDataSet();
PageInfo<Data> pageInfo = new PageInfo<>(list);

Spring Data JPA分页 直接使用Pageable接口:

Page<Data> page = repository.findAll(
    PageRequest.of(pageNum, pageSize, Sort.by("createTime").descending())
);

深度分页优化策略

游标分页(Keyset Pagination) 基于最后记录ID的连续分页:

SELECT * FROM large_table 
WHERE id > lastId AND create_time < '2023-01-01'
ORDER BY id ASC
LIMIT 1000

缓存热门分页数据 使用Redis缓存前N页数据:

String cacheKey = "page:" + pageNum;
String json = redisTemplate.opsForValue().get(cacheKey);
if(json == null) {
    Page<Data> page = fetchFromDatabase(pageNum);
    redisTemplate.opsForValue().set(cacheKey, serialize(page));
}

性能监控与调优

启用慢查询日志监控分页SQL:

-- MySQL配置
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;

使用EXPLAIN分析执行计划:

EXPLAIN SELECT * FROM large_table LIMIT 10000, 100

前端协同优化方案

实现无限滚动代替传统分页控件,减少翻页请求。采用预加载机制,当用户滚动到页面底部前50px时异步加载下一页数据。分页器显示逻辑优化:

// 伪代码示例
window.addEventListener('scroll', () => {
    if((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 50) {
        loadNextPage();
    }
});

更多推荐