MySQL Paginierung ohne Doppelabfrage?
Ich Frage mich, ob es war ein Weg, um die Anzahl von Ergebnissen aus einer MySQL-Abfrage, und zur gleichen Zeit, begrenzen Sie die Ergebnisse.
Die Art, wie die Paginierung funktioniert (wie ich es verstehe), ich zuerst etwas tun, wie
query = SELECT COUNT(*) FROM `table` WHERE `some_condition`
Nachdem ich die num_rows(query), habe ich die Anzahl der Ergebnisse. Aber dann, eigentlich beschränken sich meine Ergebnisse habe ich auf eine zweite Anfrage wie folgt:
query2 = SELECT COUNT(*) FROM `table` WHERE `some_condition` LIMIT 0, 10
Meine Frage: Ist es trotzdem auf beiden abrufen der Gesamtzahl der Ergebnisse, die würde gegeben werden, UND begrenzen Sie die zurückgegebenen Ergebnisse in einer einzigen Abfrage? Oder mehr effiziente Art, dies zu tun. Danke!
InformationsquelleAutor der Frage ash | 2009-05-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nein, das ist, wie viele Anwendungen, die umbrechen möchten haben, es zu tun. Es ist zuverlässig und Kugel-Beweis, allerdings macht es die Abfrage zweimal. Aber Sie können cache die Anzahl der für ein paar Sekunden, und das wird helfen, eine Menge.
Die andere Möglichkeit ist die Verwendung
SQL_CALC_FOUND_ROWS
- Klausel und rufen Sie dannSELECT FOUND_ROWS()
. abgesehen von der Tatsache, dass Sie haben, um dieFOUND_ROWS()
rufen danach, gibt es ein problem: Es ist ein Fehler in MySQLdass das kitzelt, wirktORDER BY
Abfragen, so dass es viel langsamer bei großen Tabellen als der naive Ansatz, der zwei Abfragen.InformationsquelleAutor der Antwort staticsan
Ich fast nie mache zwei Abfragen.
Schicken Sie einfach eine Zeile mehr als nötig, nur anzeigen, 10 auf der Seite, und wenn es mehr als angezeigt, die Anzeige einen "Weiter" - button.
Ihre Abfrage zurückgeben soll, in eine Reihenfolge der wichtigsten ersten. Chancen sind, die meisten Menschen nicht gehen, um Pflege zu gehen, um Seite 236 von 412.
Wenn Sie eine google-Suche und Ihre Ergebnisse nicht auf der ersten Seite, sind Sie wahrscheinlich gehen Sie zu Seite zwei, nicht neun.
InformationsquelleAutor der Antwort Derrick
Ein weiterer Ansatz zur Vermeidung von doppelten Abfragen wird zum abrufen aller Zeilen der aktuellen Seite mit einer LIMIT-Klausel zunächst, dann, nur eine Sekunde, COUNT(*) Abfrage, wenn die maximale Anzahl von Zeilen abgerufen wurden.
In vielen Anwendungen, das wahrscheinlichste Ergebnis wird sein, dass alle Ergebnisse auf eine Seite passen, und das tun die Paginierung ist eher die Ausnahme als die norm. In diesen Fällen, die erste Abfrage nicht abgerufen werden, die maximale Anzahl der Ergebnisse.
Beispielsweise Antworten auf einer stackoverflow-Frage selten spill auf einer zweiten Seite. Kommentare auf eine Antwort selten verschütten über die Grenze von 5 oder so erforderlich, um zu zeigen Sie alle.
So, in diesen Anwendungen können Sie einfach nur eine Abfrage mit einem LIMIT ersten, und dann solange das limit nicht erreicht ist, wissen Sie genau, wie viele Zeilen es sind, ohne die Notwendigkeit für eine zweite COUNT(*) Abfragen - das sollte die meisten Situationen.
InformationsquelleAutor der Antwort thomasrutter
In den meisten Fällen ist es viel schneller und weniger ressourcenintensiv zu tun, es in zwei separate Abfragen zu tun als es in einem, obwohl das scheint counter-intuitive.
Wenn du SQL_CALC_FOUND_ROWS, dann für große Tabellen, es macht die Abfrage sehr viel langsamer, erheblich langsamer sogar als Ausführung mit zwei Abfragen, die zunächst mit einem COUNT(*) und die zweite mit einem LIMIT. Der Grund dafür ist, dass SQL_CALC_FOUND_ROWS bewirkt, dass die LIMIT-Klausel angewendet werden nach das abrufen der Zeilen statt vor, so dass es holt die ganze Zeile für alle möglichen Ergebnisse vor der Anwendung die Grenzen. Dies kann nicht damit zufrieden sein, ein index, weil es eigentlich holt sich die Daten.
Wenn du die beiden Abfragen Ansatz, die erste nur Holen COUNT(*) und eigentlich nicht Holen-und ist-Daten, diese können zufrieden sein, viel mehr schnell, weil es in der Regel können Indizes verwenden, und nicht zum abrufen der aktuellen Zeile die Daten für jede Zeile, die es sieht. Dann, die zweite Abfrage braucht nur zu schauen, die ersten $offset+$limit Zeilen und dann zurückkehren.
Dieser Beitrag von der 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 über die Optimierung Paginierung, überprüfen dieser Beitrag und dieser Beitrag.
InformationsquelleAutor der Antwort thomasrutter
InformationsquelleAutor der Antwort Cris McLaughlin
Meine Antwort spät, aber Sie können überspringen Sie die zweite Abfrage (mit der Grenze) und filtern nur die Informationen über Ihren back-end-Skript. In PHP zum Beispiel könnten Sie so etwas wie:
Aber natürlich, wenn Sie Tausende von Datensätzen zu berücksichtigen, wird es ineffizient ist sehr schnell. Pre-berechnet, zählen vielleicht eine gute Idee zu schauen.
Hier ist eine gute Lektüre zu dem Thema:
http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf
InformationsquelleAutor der Antwort Kama
Können Sie verwenden die meisten die Abfrage in eine Unterabfrage, und setzen Sie es auf einen Bezeichner. Zum Beispiel einen Film Abfrage, die feststellt, Filme mit dem Buchstaben " s " - Bestellung mit der Laufzeit würde dann so Aussehen auf meiner Website.
Tun, beachten Sie, dass ich kein Datenbank-Experte, und bin der Hoffnung, jemand wird in der Lage sein zu optimieren, dass ein bisschen besser ist. So wie es da steht, läuft es direkt aus der SQL-Befehlszeile Schnittstelle, die Sie beide nehmen ~0,02 Sekunden auf meinem laptop.
InformationsquelleAutor der Antwort Philip Rollins
InformationsquelleAutor der Antwort John