Heim > Datenbank > MySQL-Tutorial > Mysql-Lösung zur Optimierung der Paging-Abfrage für große Tabellen

Mysql-Lösung zur Optimierung der Paging-Abfrage für große Tabellen

步履不停
Freigeben: 2019-06-25 16:05:54
Original
4925 Leute haben es durchsucht

Mysql-Lösung zur Optimierung der Paging-Abfrage für große Tabellen

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

    Der erste Fall
  1. (mit den beiden sind eigentlich gleich): Zur nächsten Seite springen, Abfragebedingungen hinzufügen: id>lastEndId limit 10
  2. Der zweite Fall
  3. : Seite nach unten blättern, zur nächsten beliebigen Seite springen, den neuen newOffset=offset-lastEndOffset,Abfrage hinzufügen Bedingungen: id>lastEndId offset newOffset limit 10, aber wenn newOffset immer noch sehr groß ist, können wir beispielsweise direkt von der ersten Seite zur letzten Seite springen. Zu diesem Zeitpunkt können wir entsprechend der umgekehrten Reihenfolge der ID abfragen (wenn die Die ursprüngliche ID ist in positiver Reihenfolge, ändern Sie sie in umgekehrte Reihenfolge. Wenn sie in umgekehrter Reihenfolge ist, ändern Sie sie in positive Reihenfolge. Berechnen Sie den Offset und den Grenzwert, der der Abfrage in umgekehrter Reihenfolge entspricht, basierend auf der Gesamtzahl, dann newOffset = totalCount - offset - limit, Abfragebedingung: id=totalCount ist die Berechnung newOffset kann kleiner als 0 sein, daher ist newOffset=0, limit = totalCount - offset
  4. Der dritte Fall
  5. der letzten Seite: Seite nach oben drehen, zu einer beliebigen Seite springen Seite oben, in umgekehrter Reihenfolge entsprechend der ID, newOffset = lastEndOffset- offset - limit-1, Abfragebedingung: id

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 addiert

lastEndCount 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++;
						}
					}
                }
                
            }
        });
Nach dem Login kopieren

Weitere technische Artikel zu MySQL finden Sie bitte Besuchen Sie die Spalte

MySQL-Tutorial

, um mehr zu erfahren!

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

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage