집 >데이터 베이스 >MySQL 튜토리얼 >MySQL 대형 테이블 페이징 쿼리 페이지 전환 최적화 계획
mysql 페이징 쿼리는 먼저 모든 데이터를 쿼리한 다음 오프셋을 건너뛰고 제한 레코드를 가져오므로 페이지 수가 길어질수록 쿼리 시간도 길어집니다. # 🎜🎜#
일반적인 최적화 아이디어는 오프셋을 가능한 한 작게 만들기 위해 오프셋을 변환하는 것입니다. 매번 첫 번째 페이지를 쿼리하는 것이 가장 좋습니다. 즉, 오프셋은 0#🎜 🎜#
ID로 정렬된 쿼리
1. 쿼리가 ID로 정렬되고 ID가 연속된 경우# 🎜🎜#이것은 확인할 페이지 수를 기준으로 ID 범위를 직접 계산할 수 있는 방법이 많이 있습니다.
예를 들어 offset=40,limit=10은 쿼리를 의미합니다. 데이터가 5페이지에 있으면 5페이지에서 시작하는 ID는 41입니다. 쿼리 조건 추가: id>40 제한 102. 쿼리가 다음과 같은 경우 id를 기준으로 정렬했지만 id가 연속적이지 않습니다
보통 페이지 점프가 그리 크지 않기 때문에 다음 페이징 쿼리에 해당하는 새로운 오프셋과 제한을 계산할 수 있습니다. 마지막 쿼리의 레코드, 즉 이전 쿼리와의 거리 레코드 오프셋 쿼리
Paging 쿼리에는 일반적으로 오프셋과 제한이라는 두 가지 매개변수가 있습니다. 일반적으로 제한은 10으로 고정됩니다#🎜. 🎜#그런 다음 오프셋이 너무 큰 상황을 최적화하려면 각 쿼리에서 두 개의 추가 매개 변수를 제공해야 합니다.
Parameter lastEndId: 이전 쿼리의 마지막 레코드 ID# 🎜🎜#
Parameter lastEndOffset: 이전 쿼리의 마지막 레코드에 해당합니다. 오프셋, 즉 마지막 쿼리의 오프셋+한계 첫번째 case(실제로 두 번째와 동일): 다음 한 페이지로 이동, 쿼리 조건 추가: id>lastEndId 제한 10
두 번째 경우에서 계산된 newOffset에 lastEndCount를 추가합니다. 이는 새로운 오프셋입니다. 두 번째 것과 동일
java 예:
MySQLTutorial 위 내용은 MySQL 대형 테이블 페이징 쿼리 페이지 전환 최적화 계획의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!/**
* 如果是根据创建时间排序的分页,根据上一条记录的创建时间优化分布查询
*
* @see 将会自动添加createTime排序
* @param lastEndCreateTime
* 上一次查询的最后一条记录的创建时间
* @param lastEndCount 上一次查询的时间为lastEndCreateTime的数量
* @param lastEndOffset 上一次查询的最后一条记录对应的偏移量 offset+limit
**/
public Page<T> page(QueryBuilder queryBuilder, Date lastEndCreateTime, Integer lastEndCount, Integer lastEndOffset,
int offset, int limit) {
FromBuilder fromBuilder = queryBuilder.from(getModelClass());
Page<T> page = new Page<>();
int count = dao.count(fromBuilder);
page.setTotal(count);
if (count == 0) {
return page;
}
if (offset == 0 || lastEndCreateTime == null || lastEndCount == null || lastEndOffset == null) {
List<T> list = dao.find(
SelectBuilder.selectFrom(fromBuilder.offsetLimit(offset, limit).order().desc("createTime").end()));
page.setData(list);
return page;
}
boolean isForward = offset >= lastEndOffset;
if (isForward) {
int calcOffset = offset - lastEndOffset + lastEndCount;
int calcOffsetFormEnd = count - offset - limit;
if (calcOffsetFormEnd <= calcOffset) {
isForward = false;
if (calcOffsetFormEnd > 0) {
fromBuilder.order().asc("createTime").end().offsetLimit(calcOffsetFormEnd, limit);
} else {
fromBuilder.order().asc("createTime").end().offsetLimit(0, calcOffsetFormEnd + limit);
}
} else {
fromBuilder.where().andLe("createTime", lastEndCreateTime).end().order().desc("createTime").end()
.offsetLimit(calcOffset, limit);
}
} else {
fromBuilder.where().andGe("createTime", lastEndCreateTime).end().order().asc("createTime").end()
.offsetLimit(lastEndOffset - offset - limit - 1 + lastEndCount, limit);
}
List<T> list = dao.find(SelectBuilder.selectFrom(fromBuilder));
if (!isForward) {
list.sort(new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
return o1.getCreateTime().before(o2.getCreateTime()) ? 1 : -1;
}
});
}
page.setData(list);
return page;
} <p> 부트스트랩 테이블을 기반으로 한 프런트 엔드 js 매개변수</p>
<pre class="brush:php;toolbar:false"> this.lastEndCreateTime = null;
this.currentEndCreateTime = null;
this.isRefresh = false;
this.currentEndOffset = 0;
this.lastEndOffset = 0;
this.lastEndCount = 0;
this.currentEndCount = 0;
$("#" + this.tableId).bootstrapTable({
url: url,
method: 'get',
contentType: "application/x-www-form-urlencoded",//请求数据内容格式 默认是 application/json 自己根据格式自行服务端处理
dataType:"json",
dataField:"data",
pagination: true,
sidePagination: "server", // 服务端请求
pageList: [10, 25, 50, 100, 200],
search: true,
showRefresh: true,
toolbar: "#" + tableId + "Toolbar",
iconSize: "outline",
icons: {
refresh: "icon fa-refresh",
},
queryParams: function(params){
if(params.offset == 0){
this.currentEndOffset = params.offset + params.limit;
}else{
if(params.offset + params.limit==this.currentEndOffset){
//刷新
this.isRefresh = true;
params.lastEndCreateTime = this.lastEndCreateTime;
params.lastEndOffset = this.lastEndOffset;
params.lastEndCount = this.lastEndCount;
}else{
console.log(this.currentEndCount);
//跳页
this.isRefresh = false;
params.lastEndCreateTime = this.currentEndCreateTime;
params.lastEndOffset = this.currentEndOffset;
params.lastEndCount = this.currentEndCount;
this.lastEndOffset = this.currentEndOffset;
this.currentEndOffset = params.offset + params.limit;
console.log(params.lastEndOffset+","+params.lastEndCreateTime);
}
}
return params;
},
onSearch: function (text) {
this.keyword = text;
},
onPostBody : onPostBody,
onLoadSuccess: function (resp) {
if(resp.code!=0){
alertUtils.error(resp.msg);
}
var data = resp.data;
var dateLength = data.length;
if(dateLength==0){
return;
}
if(!this.isRefresh){
this.lastEndCreateTime = this.currentEndCreateTime;
this.currentEndCreateTime = data[data.length-1].createTime;
this.lastEndCount = this.currentEndCount;
this.currentEndCount = 0;
for (var i = 0; i < resp.data.length; i++) {
var item = resp.data[i];
if(item.createTime === this.currentEndCreateTime){
this.currentEndCount++;
}
}
}
}
});
#🎜 🎜#더 많은 MySQL 관련 기술 기사를 보려면