Frage

Ich habe eine aktuelle Implementierung von will_paginate , die die paginate_by_sql Methode verwendet, die Sammlung zu bauen paginierte werden. Wir haben eine benutzerdefinierte Abfrage für total_entries , das ist sehr kompliziert und stellt eine große Belastung unserer DB. Daher möchten wir total_entries von der Paginierung ganz schneiden.

Mit anderen Worten, statt der typischen Paginierung Anzeige von ‚vorherigen 1 [2] 3 4 5 next‘, wir würde einfach wie eine ‚next - vorherige‘ Taste nur. Aber wir müssen ein paar Dinge wissen.

  1. wir den vorherigen Link anzeigen Sie? Dies würde natürlich nur auftreten, wenn Aufzeichnungen vor den in der aktuellen Auswahl
  2. angezeigten Einsen bestehende
  3. wir zum nächsten Link angezeigt werden Sie? Dies wäre nicht angezeigt, wenn der letzte Datensatz in der Sammlung angezeigt wird

Von der docs

  

Eine Abfrage zum Zählen von Zeilen werden   automatisch, wenn Sie erzeugt werden   nicht liefern: total_entries. Wenn du   Erfahrung Probleme mit diesem   generierten SQL, möchten Sie vielleicht   durchführen manuell die Zählung in Ihrem   Anwendung.

So ist letztlich die ideale Situation ist die folgende.

  • Entfernen zählen die total_entries, weil es zu viel Last auf die Datenbank zu verursachen
  • Display 50 Datensätze gleichzeitig mit halb-Paginierung nur nächsten / vorherigen Tasten, um zu navigieren und nicht alle Seitenzahlen angezeigt werden verfügbar
  • Es wird nur angezeigt werden, die nächste Taste und vorherige Taste entsprechend

Hat jemand mit einem ähnlichen Problem gearbeitet oder Gedanken über eine Lösung?

War es hilfreich?

Lösung

Es gibt viele Gelegenheiten, bei denen will_paginate eine wirklich schreckliche Arbeit erledigt, die Anzahl der Einträge zu berechnen, vor allem wenn es Joins beteiligt, die die Zählung SQL-Generator verwechseln.

Wenn Sie nur eine einfache prev / next-Methode ist, dann alles, was Sie tun müssen, um zu versuchen, ist N + 1 Einträge aus der Datenbank abgerufen wird, und wenn Sie nur N oder weniger bekommen, als Sie auf der letzten Seite sind.

Zum Beispiel:

per_page = 10
page = 2

@entries = Thing.with_some_scope.find(:all, :limit => per_page + 1, :offset => (page - 1) * per_page)

@next_page = @entries.slice!(per_page, 1)
@prev_page = page > 1

Sie können dies leicht einkapseln in einigen Modul, das in den verschiedenen Modellen enthalten sein können, die sie benötigen, oder einen Controller-Erweiterung machen.

Ich habe festgestellt, dass dies funktioniert deutlich besser als die Standard will_paginate Methode.

Das einzige Performance-Problem ist eine Beschränkung von MySQL, die ein Problem in Abhängigkeit von der Größe der Tabellen sein können.

Für welchen Gründen auch immer, die Zeit, dauert es eine Abfrage mit einem kleinen LIMIT in MySQL auszuführen ist proportional zur OFFSET. Tatsächlich liest der Datenbank-Engine durch alle Reihen auf den jeweiligen Offset-Wert führen, dann die Zeilen nächste LIMIT Zahl zurück gehen, nicht voraus, wie man erwarten würde.

Bei großen Datensätzen, in denen Sie die Werte in der 100.000 plus-Bereich OFFSET haben sollten, können Sie die Leistung finden verschlechtert erheblich. Wie dies offensichtlich ist, dass Lade Seite 1 sehr schnell, Seite 1000 etwas langsam, aber Seite 2000 ist extrem langsam.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top