Ich habe mich gefragt, ob es eine Möglichkeit gibt, die Anzahl der Ergebnisse einer MySQL-Abfrage zu ermitteln und gleichzeitig die Ergebnisse zu begrenzen.
So wie Paginierung funktioniert (so wie ich es verstehe), mache ich zuerst so etwas
query = SELECT COUNT(*) FROM `table` WHERE `some_condition`
Nachdem ich die num_rows (Abfrage) erhalten habe, habe ich die Anzahl der Ergebnisse. Aber um meine Ergebnisse tatsächlich einzuschränken, muss ich eine zweite Abfrage durchführen wie:
query2 = SELECT COUNT(*) FROM `table` WHERE `some_condition` LIMIT 0, 10
Meine Frage: Gibt es überhaupt eine Möglichkeit, die Gesamtzahl der angegebenen Ergebnisse abzurufen UND die in einer einzelnen Abfrage zurückgegebenen Ergebnisse zu begrenzen? Oder eine effizientere Art, dies zu tun. Vielen Dank!
mysql
pagination
double
atp
quelle
quelle
Antworten:
Nein, so viele Anwendungen, die paginieren möchten, müssen dies tun. Es ist zuverlässig und kugelsicher, obwohl die Abfrage zweimal durchgeführt wird. Sie können die Anzahl jedoch für einige Sekunden zwischenspeichern, was sehr hilfreich ist.
Die andere Möglichkeit besteht darin, die
SQL_CALC_FOUND_ROWS
Klausel zu verwenden und dann aufzurufenSELECT FOUND_ROWS()
. Abgesehen von der Tatsache, dass Sie denFOUND_ROWS()
Aufruf anschließend tätigen müssen, gibt es ein Problem damit: Es gibt einen Fehler in MySQL , der kitzelt und sich aufORDER BY
Abfragen auswirkt, wodurch er in großen Tabellen viel langsamer ist als der naive Ansatz von zwei Abfragen.quelle
Ich mache fast nie zwei Abfragen.
Geben Sie einfach eine Zeile mehr als erforderlich zurück, zeigen Sie nur 10 auf der Seite an, und wenn mehr als angezeigt werden, zeigen Sie die Schaltfläche "Weiter" an.
Ihre Anfrage sollte zuerst in der Reihenfolge der relevantesten zurückgegeben werden. Wahrscheinlich kümmern sich die meisten Leute nicht darum, von 412 auf Seite 236 zu gehen.
Wenn Sie eine Google-Suche durchführen und Ihre Ergebnisse nicht auf der ersten Seite angezeigt werden, wechseln Sie wahrscheinlich zu Seite zwei und nicht zu neun.
quelle
COUNT
ist eine Aggregatfunktion. Wie geben Sie die Anzahl und alle Ergebnisse in einer Abfrage zurück? Die obige Abfrage gibt nur 1 Zeile zurück, unabhängig davon, auf welcheLIMIT
eingestellt ist. Wenn Sie hinzufügenGROUP BY
, gibt es alle Ergebnisse zurück, aber dasCOUNT
wird ungenau seinEin anderer Ansatz zur Vermeidung von Doppelabfragen besteht darin, zuerst alle Zeilen für die aktuelle Seite mit einer LIMIT-Klausel abzurufen und dann nur dann eine zweite COUNT (*) -Abfrage durchzuführen, wenn die maximale Anzahl von Zeilen abgerufen wurde.
In vielen Anwendungen ist das wahrscheinlichste Ergebnis, dass alle Ergebnisse auf eine Seite passen und die Paginierung eher die Ausnahme als die Norm ist. In diesen Fällen ruft die erste Abfrage nicht die maximale Anzahl von Ergebnissen ab.
Beispielsweise werden Antworten auf eine Stapelüberlauffrage selten auf eine zweite Seite übertragen. Kommentare zu einer Antwort überschreiten selten das Limit von 5 oder so, um sie alle anzuzeigen.
In diesen Anwendungen können Sie also einfach zuerst eine Abfrage mit einem LIMIT durchführen. Solange dieses Limit nicht erreicht ist, wissen Sie genau, wie viele Zeilen vorhanden sind, ohne dass eine zweite COUNT (*) - Abfrage erforderlich ist decken die meisten Situationen ab.
quelle
In den meisten Situationen ist es viel schneller und weniger ressourcenintensiv, dies in zwei separaten Abfragen zu tun, als in einer, obwohl dies nicht intuitiv zu sein scheint.
Wenn Sie SQL_CALC_FOUND_ROWS verwenden, wird Ihre Abfrage bei großen Tabellen viel langsamer und sogar deutlich langsamer als bei der Ausführung von zwei Abfragen, die erste mit COUNT (*) und die zweite mit LIMIT. Der Grund dafür ist , dass SQL_CALC_FOUND_ROWS die LIMIT - Klausel angewendet werden verursacht nach Abrufen der Zeilen anstelle von zuvor , sodass die gesamte Zeile für alle möglichen Ergebnisse bevor die Grenzwerte . Dies kann von einem Index nicht erfüllt werden, da er die Daten tatsächlich abruft.
Wenn Sie den Ansatz mit zwei Abfragen wählen, wobei der erste nur COUNT (*) abruft und nicht tatsächlich Daten abruft, kann dies viel schneller erfüllt werden, da normalerweise Indizes verwendet werden können und die tatsächlichen Zeilendaten nicht abgerufen werden müssen jede Zeile, die es betrachtet. Dann muss die zweite Abfrage nur die ersten Zeilen $ offset + $ limit betrachten und dann zurückkehren.
Dieser Beitrag aus dem MySQL-Performance-Blog erklärt dies weiter:
http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Weitere Informationen zur Optimierung der Paginierung finden Sie in diesem Beitrag und in diesem Beitrag .
quelle
Meine Antwort mag verspätet sein, aber Sie können die zweite Abfrage (mit dem Limit) überspringen und die Informationen einfach durch Ihr Back-End-Skript filtern. In PHP können Sie beispielsweise Folgendes tun:
Aber wenn Sie Tausende von Datensätzen berücksichtigen müssen, wird dies natürlich sehr schnell ineffizient. Eine vorberechnete Anzahl ist vielleicht eine gute Idee.
Hier ist eine gute Lektüre zu diesem Thema: http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf
quelle
quelle
where
Klausel zur inneren Abfrage hinzu und Sie erhalten die richtige "Summe" zusammen mit den ausgelagerten Ergebnissen (Seite wird mit derlimit
Klausel ausgewähltFür alle, die 2020 nach einer Antwort suchen. Gemäß MySQL-Dokumentation:
"Der SQL_CALC_FOUND_ROWS-Abfragemodifikator und die zugehörige FOUND_ROWS () -Funktion sind ab MySQL 8.0.17 veraltet und werden in einer zukünftigen MySQL-Version entfernt. Als Ersatz sollten Sie Ihre Abfrage mit LIMIT ausführen und anschließend eine zweite Abfrage mit COUNT (*). und ohne LIMIT, um festzustellen, ob zusätzliche Zeilen vorhanden sind. "
Ich denke, das regelt das.
https://dev.mysql.com/doc/refman/8.0/de/information-functions.html#function_found-rows
quelle
Sie können den größten Teil der Abfrage in einer Unterabfrage wiederverwenden und auf einen Bezeichner setzen. Zum Beispiel würde eine Filmabfrage, die Filme findet, die die Reihenfolge der Buchstaben nach Laufzeit enthalten, auf meiner Website so aussehen.
Beachten Sie, dass ich kein Datenbankexperte bin und hoffe, dass jemand dies ein bisschen besser optimieren kann. Da es direkt über die SQL-Befehlszeilenschnittstelle ausgeführt wird, benötigen beide auf meinem Laptop ~ 0,02 Sekunden.
quelle
quelle