Maison >base de données >tutoriel mysql >Solution d'optimisation de rotation de page de requête de pagination de grande table Mysql
La requête de pagination Mysql interroge d'abord toutes les données, puis ignore le décalage et prend les enregistrements limites, ce qui entraîne que plus le nombre de pages est élevé, plus le temps de requête est long
L'idée générale d'optimisation est de convertir le décalage pour le rendre aussi petit que possible. Il est préférable d'interroger la première page à chaque fois, c'est-à-dire que le décalage est de 0
lorsque la requête est triée par identifiant
1 Si la requête est triée par identifiant et que l'identifiant est continu
Il existe de nombreuses introductions en ligne, et l'identifiant peut être calculé directement en fonction du nombre de pages à vérifier. La plage de , par exemple, offset=40, limit=10, signifie interroger les données de la page 5, puis l'identifiant à partir de la page 5. est 41, ajoutez des conditions de requête : id>40 limite 102 Si la requête est triée selon l'identifiant, mais que l'identifiant n'est pas continu .
Habituellement, le nombre de sauts de page ne sera pas très grand, alors nous pouvons, en fonction de ce qui précède. Pour les enregistrements d'une requête, calculer le nouveau décalage et la limite correspondant à la prochaine requête de pagination, qui est le décalage de l'enregistrement de requête précédent. Les requêtes de pagination ont généralement deux paramètres : offset et limit. La limite est généralement fixe, en supposant que limit=10 Afin d'optimiser la situation où le décalage est trop grand, deux paramètres supplémentaires. doivent être fournis pour chaque requête Paramètre lastEndId : L'identifiant du dernier enregistrement de la requête précédenteParamètre lastEndOffset : Le décalage correspondant au dernier enregistrement de la dernière requête, c'est-à-dire le décalage+limite de la dernière requêteSi la requête est triée en fonction d'autres champs, tels que l'heure de création couramment utilisée (createTime)
C'est la même chose que la seconde. Les deux situations sont similaires. La différence est que createTime n'est pas unique, il est donc impossible de déterminer l'heure de création correspondant au dernier enregistrement, lesquels sont pour la page suivante et lesquels sont pour la page suivante. la page précédente A ce moment, ajoutez un paramètre de requête lastEndCount : Indique l'heure de création correspondant au dernier enregistrement dans la dernière requête, et combien d'enregistrements sont en même temps. Ceci est basé sur les dernières données. statistiqueset est ajouté au newOffset calculé dans le deuxième cas lastEndCount est le nouveau décalage. Les autres méthodes de traitement sont les mêmes que la seconde
<. 🎜>Exemple Java :
/** * 如果是根据创建时间排序的分页,根据上一条记录的创建时间优化分布查询 * * @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>Paramètres js front-end, basés sur la table d'amorçage</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++; } } } } });
Pour plus d'articles techniques liés à MySQL , veuillez visiter la colonne
Tutoriel MySQLCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!