引言
在现代Web应用和移动应用中,面对大量数据的展示,分页技术成为了提升用户体验和优化数据加载效率的关键手段。尤其是在MySQL数据库环境中,合理运用分页查询不仅能显著减少服务器负载,还能提升数据访问速度,为用户提供流畅的浏览体验。本文将深入探讨分页的概念、实现原理,以及如何在MySQL中高效地执行分页查询,结合丰富的代码示例和实战技巧,帮助你掌握这一核心技能。
分页的基本概念和作用
分页是指将大数据集分割成一系列较小的数据块(即页面),每次仅加载其中一部分数据供用户查看。这种策略有效解决了一次性加载全部数据可能导致的性能瓶颈问题,同时也让用户能够更加轻松地管理和浏览数据。
页(Page)
数据分割后的独立单元,每页包含固定数量的数据条目(如 10 条、20 条)。
页码(Page Number)
标识当前显示的是第几页,通常从 1 开始计数。
每页数量(Page Size)
每页显示的数据条目数,如 page_size=10。
总页数(Total Pages)
基于总数据量和每页数量计算得出:总页数 = ceil(总数据量 / 每页数量)。
分页的作用
- 性能优化:减少单次查询的数据量,降低网络传输负担和数据库负载。
- 用户体验:提高页面加载速度,使用户操作更加流畅。
- 资源节约:避免不必要的数据传输和处理,节省带宽和计算资源。
分页实现原理
每次请求仅从数据库查询当前页的数据,通过 SQL 的 LIMIT
和 OFFSET
实现。
SELECT * FROM table ORDER BY id LIMIT 10 OFFSET 20; -- 第3页(每页10条)
优点:减少数据库和服务器的负载,适合大数据量。
缺点:频繁的数据库查询可能影响性能(尤其是 OFFSET 较大时)。
实例:
html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="js/jquery-3.7.1.min.js"></script>
<script src="js/jquery.cookie.min.js"></script>
<script src="js/student.js" defer></script>
<style type='text/css'>
.page{
display:flex;
margin-left:-40px;
}
.page li{
list-style:none;
border:1px solid #444;
font-size:14px;
padding:3px;
cursor:pointer;
margin-right:5px;
}
.page li.current{
background:#444;
color:#fff;
}
</style>
</head>
<body>
<input type='button' value='添加' class='add'>
<table border ="1">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<ul class='page'>
<!--<li>首页<>
<li>上一页<>
<li>1<>
<li>2<>
<li>3<>
<li>4<>
<li>下一页<>
<li>尾页<>-->
</ul>
</body>
</html>
js页面:
var page = 1
var pageSize = 6
//查找学生
var loadDate = function(){
$.ajax({
url:"SearchServlet1",
type:"get",
data:{
page,
pageSize
},
success:function(value){
var arr = value.data
$("tbody").empty()
for(var i=0;i<arr.length;i++){
$("tbody").append("<tr>"+
"<td>"+arr[i].id+"</td>"+
"<td>"+arr[i].name+"</td>"+
"<td>"+arr[i].age+"</td>"+
"<td>"+arr[i].sex+"</td>"+
"<td><input type='button' value='修改' class='update' index='"+arr[i].id+"'><input type='button' value='删除' class='delete' index='"+arr[i].id+"'> </td>"+
"</tr>")
}
},
error:function(){
alert("出错了")
},
})
}
//加载页码
$.ajax({
url:"GetCountServlet",
type:"get",
success:function(value){
$(".page").append("<li class='first'>首页</li>")
$(".page").append("<li class='prev'>上一页</li>")
for(var i=0;i<Math.ceil(value.num/pageSize);i++){
if(i==0){
$(".page").append("<li class='current item'>"+(i+1)+"</li>")
}else{
$(".page").append("<li class='item'>"+(i+1)+"</li>")
}
}
$(".page").append("<li class='next'>下一页</li>")
$(".page").append("<li class='last'>尾页</li>")
},
error:function(){
alert("错了")
},
})
//任意页码切换
$(".page").on("click",".item",function(){
page=$(this).text()
loadDate();
$(this).addClass("current")
$(this).siblings().removeClass("current")
})
//首页
$(".page").on("click",".first",function(){
page=1
loadDate();
$(".item").removeClass("current")
$(".item").first().addClass("current")
})
//尾页
$(".page").on("click",".last",function(){
page=$(".this").length
loadDate();
$(".item").removeClass("current")
$(".item").last().addClass("current")
})
//上一页切换
$(".page").on("click",".prev",function(){
if(page==1){
alert("没有前一页了")
return
}
page--
loadDate()
$(".item").removeClass("current")
$(".item").eq(page-1).addClass("current")
})
//下一页切换
$(".page").on("click",".next",function(){
if(page==$(".item").length){
alert("没有下一页了")
return
}
page++
loadDate()
$(".item").removeClass("current")
$(".item").eq(page-1).addClass("current")
})
servlet代码:
package com.qcby.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.qcby.db.MysqlUtil;
/**
* Servlet implementation class SearchServlet
*/
@WebServlet("/SearchServlet1")
public class SearchServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public SearchServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String page = request.getParameter("page");
String pageSize = request.getParameter("pageSize");
String sql = "select * from student limit "+(Integer.parseInt(page)-1)*Integer.parseInt(pageSize)+","+pageSize;
String[] colums = {"id","name","age","sex"};
String res = MysqlUtil.getJsonBySql(sql, colums);
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(res);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.qcby.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.qcby.db.MysqlUtil;
/**
* Servlet implementation class GetCountServlet
*/
@WebServlet("/GetCountServlet")
public class GetCountServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public GetCountServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String sql="select count(*) from rooms";
int num=MysqlUtil.getCount(sql);
String res="{\"num\":"+num+"}";
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(res);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
笔记:
1. for(var i=0;i<Math.ceil(value.num/pageSize);i++)
主要功能是基于给定的总数量value.num
与每页显示数量pageSize
,算出所需的总页数,接着对这些页面进行遍历。Math.ceil()
是 JavaScript 中的一个内置函数,属于 Math
对象。它的作用是向上取整,即返回大于或等于给定数字的最小整数。
2. $(this).addClass("current")$(this).siblings().removeClass("current")
给当前页面添加class,其兄弟姐妹都不能使用这个类。方便样式添加。
3. $(".item").removeClass("current") $(".item").eq(page-1).addClass("current")
page是从1开始的,而eq(page - 1)此方法会从选中的元素集合里选取索引为 page - 1
的元素。在 jQuery 中,元素的索引是从 0 开始的,所以 page - 1
表示第 page
个元素(从 1 开始计数)。因为之前有++/--所以正好对应下一个元素。
4. String page = request.getParameter("page"); String pageSize = request.getParameter("pageSize"); String sql = "select * from student limit "+(Integer.parseInt(page)-1)*Integer.parseInt(pageSize)+","+pageSize;
主要功能是从 HTTP 请求里获取 page
和 pageSize
参数,然后构建一条 SQL 查询语句,以此实现数据的分页查询 。
Integer.parseInt() 是 Java 中的一个静态方法,它属于 java.lang.Integer 类。此方法的主要用途是将字符串类型的数字转换为 int
类型的整数。