当前位置: 首页 > news >正文

MySQL大量数据偏移查询优化:从LIMIT偏移到基于ID的数据读取

在开发过程中,我们经常需要从数据库中查询大量数据,并进行分页展示或数据写入文件导出。传统的分页查询方法通常使用LIMIT语句结合偏移量(offset)来实现。然而,当数据量非常大时,这种方法会导致查询性能急剧下降,因为数据库需要扫描从起始行到偏移行之间的所有行才能找到需要的数据。本文将探讨如何从使用基于最后访问ID的分页方法,并提供Java代码案例。

1. 传统LIMIT偏移分页的问题

假设我们有一个包含数百万条记录的orders表,我们想要获取第1000页的数据,每页显示100条记录。使用LIMIT和偏移量的查询如下:

SELECT * FROM orders ORDER BY order_id ASC LIMIT 100000, 100;

这个查询需要数据库扫描前100,000条记录才能找到第100,001条到第100,100条记录。当数据量增加时,这种扫描的开销会变得非常大。

2. :基于ID的分页

为了优化分页查询,我们可以记录上一次查询的最后一条记录的ID(或任何可以唯一标识记录且有序的字段,如时间戳)。下一次查询时,我们使用这个ID作为起点来过滤数据。

步骤:

首次查询:获取第一页数据,并记录最后一条记录的ID。
后续查询:使用上一次的最后ID作为起点,查询下一页数据。

import java.sql.*;  public class PaginationExample {  private static final String URL = "jdbc:mysql://localhost:3306/yourdatabase";  private static final String USER = "yourusername";  private static final String PASSWORD = "yourpassword";  public static void main(String[] args) {  Connection conn = null;  PreparedStatement pstmt = null;  ResultSet rs = null;  try {  // 假设lastId是上一次查询的最后一个ID long lastId = 0; // 首次查询或没有上一次ID时  int pageSize = 100; // 每页大小  // 连接数据库  conn = DriverManager.getConnection(URL, USER, PASSWORD);  // 准备SQL语句,这里假设order_id是递增的  String sql = "SELECT * FROM orders WHERE order_id > ? ORDER BY order_id ASC LIMIT ?";  pstmt = conn.prepareStatement(sql);  // 设置参数  pstmt.setLong(1, lastId);  pstmt.setInt(2, pageSize);  // 执行查询  rs = pstmt.executeQuery();  // 处理结果集  while (rs.next()) {  // 假设order_id是我们要展示的数据之一  long currentId = rs.getLong("order_id");  // 处理其他字段...  System.out.println("Order ID: " + currentId);  // 更新lastId为当前处理的最后一个ID,用于下一次查询  lastId = currentId;  }  // 如果有更多数据需要查询,可以在这里递归调用或循环调用这个方法,传入新的lastId  } catch (SQLException e) {  e.printStackTrace();  } finally {  // 关闭资源  try {  if (rs != null) rs.close();  if (pstmt != null) pstmt.close();  if (conn != null) conn.close();  } catch (SQLException e) {  e.printStackTrace();  }  }  }  
}
注意

lastId是在循环中更新的,但在实际应用中,只需要在循环结束后更新它。
确保数据库表有一个递增的ID或时间戳字段。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • JavaEE 第16节 线程安全的集合类
  • 华为设备默认密码
  • 【人工智能】多模态AI:如何通过融合文本、图像与音频重塑智能系统未来
  • 【数仓建模过程】Spark数据清洗篇
  • 深入理解DPO(Direct Preference Optimization)算法
  • erlang学习:用OTP构建系统1
  • 单链表——随机链表的复制
  • Mask R-CNN论文原理讲解
  • 【C#】静态成员(static)与实例成员(非静态成员)的理解
  • macos USB外接键盘ctrl键绑定方法 解决外接USB键盘与mac键盘不一致问题
  • JVM【面试题】2024最新
  • 【C++ | 设计模式】工厂方法模式的详解与实现
  • Kompose工具:转换Compose项目为K8S项目
  • 深度强化学习算法(三)(附带MATLAB程序)
  • priority_queue模拟
  • 10个确保微服务与容器安全的最佳实践
  • css布局,左右固定中间自适应实现
  • css属性的继承、初识值、计算值、当前值、应用值
  • mongodb--安装和初步使用教程
  • orm2 中文文档 3.1 模型属性
  • VuePress 静态网站生成
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 前端面试题总结
  • 如何使用 JavaScript 解析 URL
  • 算法系列——算法入门之递归分而治之思想的实现
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • (C语言)逆序输出字符串
  • (NSDate) 时间 (time )比较
  • (搬运以学习)flask 上下文的实现
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (十八)SpringBoot之发送QQ邮件
  • (四)JPA - JQPL 实现增删改查
  • .apk文件,IIS不支持下载解决
  • .md即markdown文件的基本常用编写语法
  • .NET Remoting学习笔记(三)信道
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .net 调用php,php 调用.net com组件 --
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET企业级应用架构设计系列之技术选型
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • [100天算法】-实现 strStr()(day 52)
  • [ACM] hdu 1201 18岁生日
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数
  • [HDCTF 2023]Welcome To HDCTF 2023
  • [Mysql-DML数据操作语句]
  • [MySQL复制异常]Cannot execute statement: impossible to write to binary log since statement is in row for
  • [Poetize6] IncDec Sequence
  • [python 刷题] 2866 Beautiful Towers II
  • [python开发模拟netcat工具] BHPnet
  • [Python学习日记-12] 双色球彩票程序练习(使用到列表、判断、循环等)