Die MySQL-Paging-Abfrage fragt zunächst alle Daten ab, überspringt dann den Offset und übernimmt die Grenzdatensätze. Dies führt dazu, dass die Abfragezeit umso länger ist, je höher die Anzahl der Seiten ist
Die allgemeine Optimierungsidee besteht darin, den Versatz so umzuwandeln, dass er so klein wie möglich ist. Es ist am besten, jedes Mal die erste Seite abzufragen, das heißt, der Versatz ist 0
wenn die Abfrage nach ID sortiert ist
1. Wenn die Abfrage nach ID sortiert ist und die ID fortlaufend ist
Es gibt viele Online-Einführungen, und die ID kann Der Bereich
wird direkt anhand der Anzahl der zu prüfenden Seiten berechnet, z. B. Offset = 40, Limit = 10. Wenn die Daten auf Seite 5 abgefragt werden, lautet die ID ab Seite 5 41, Abfragebedingungen hinzufügen: id>40 limit 10
2. Wenn die Abfrage nach ID sortiert ist, die ID jedoch nicht fortlaufend ist
Normalerweise wird die Anzahl der Seitensprünge nicht sehr groß sein, dann können wir das Obige verwenden. Berechnen Sie für die Datensätze einer Abfrage den neuen Offset und den Grenzwert, der der nächsten Paging-Abfrage entspricht, also dem Offset
von Der vorherige Abfragedatensatz hat im Allgemeinen zwei Parameter: Offset und Limit. Unter der Annahme, dass Limit = 10 ist, sind zwei zusätzliche Parameter erforderlich, um die Situation zu optimieren Wird für jede Abfrage bereitgestellt
Parameter lastEndId: Die ID des letzten Datensatzes der vorherigen Abfrage
Parameter lastEndOffset: Der Offset, der dem letzten Datensatz der letzten Abfrage entspricht, d. h. der Offset+ Limit der letzten Abfrage
Drittens,
Wenn die Abfrage nach anderen Feldern sortiert ist, z. B. nach der häufig verwendeten Erstellungszeit (createTime)Dies ist das gleiche wie beim zweiten Die beiden Situationen sind ähnlich. Der Unterschied besteht darin, dass createTime nicht eindeutig ist, sodass es unmöglich ist, die Erstellungszeit des letzten Datensatzes zu bestimmen, welche für die nächste Seite und welche für die vorherige gelten Seite
Fügen Sie zu diesem Zeitpunkt einen Anforderungsparameter lastEndCount hinzu: Gibt die Erstellungszeit an, die dem letzten Datensatz in der letzten Abfrage entspricht, und wie viele Datensätze gleichzeitig vorhanden sind. Dies basiert auf der letzten Datenstatistik
und wird zum im zweiten Fall berechneten newOffset addiertlastEndCount ist der neue Versatz
Java-Beispiel:
/** * 如果是根据创建时间排序的分页,根据上一条记录的创建时间优化分布查询 * * @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> </p> <p>Front-End-JS-Parameter, basierend auf der Bootstrap-Tabelle</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++; } } } } });
Weitere technische Artikel zu MySQL finden Sie bitte Besuchen Sie die Spalte
MySQL-TutorialDas obige ist der detaillierte Inhalt vonMysql-Lösung zur Optimierung der Paging-Abfrage für große Tabellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!