Maison  >  Article  >  base de données  >  Solution d'optimisation de rotation de page de requête de pagination de grande table Mysql

Solution d'optimisation de rotation de page de requête de pagination de grande table Mysql

步履不停
步履不停original
2019-06-25 16:05:544819parcourir

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 10

2 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édente

Paramè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ête

  1. Le premier cas (avec le Les deux sont en fait identiques) : passer à la page suivante, ajouter des conditions de requête : id>lastEndId limite 10
  2. Le deuxième cas : tourner la page, passer à la page arbitraire suivante, calculer le nouveau newOffset=offset-lastEndOffset,Ajouter des conditions de requête : id>lastEndId offset newOffset limite 10, mais si newOffset est toujours très grand, par exemple, directement à partir de la première page Passer à la dernière page À ce stade, nous pouvons interroger en fonction de l'ordre inverse de l'ID. (si l'ID d'origine est dans l'ordre positif, changez-le en ordre inverse, s'il s'agit d'un ordre inverse, changez-le en ordre positif), et calculez le décalage et la limite correspondant à la requête d'ordre inverse en fonction du nombre total, puis newOffset = totalCount - offset - limit, condition de requête : id=totalCount, cela. est Le newOffset calculé peut être inférieur à 0, donc le newOffset=0 de la dernière page, limit = totalCount - offset
  3. Le troisième cas : tournez la page vers le haut, Accédez à n'importe quelle page ci-dessus, inversez l'ordre en fonction de l'identifiant, newOffset = lastEndOffset- offset - limit-1, condition de requête : id

Troisièmement,

Si 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. statistiques

et 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 MySQL

pour apprendre !

Ce 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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn