Warum brauchen wir instrumentelle UnterstĂŒtzung fĂŒr die Paginierung auf Tasten?

Hallo zusammen! Ich bin ein Backend-Entwickler, der Microservices in Java + Spring schreibt. Ich arbeite in einem der internen Produktentwicklungsteams bei Tinkoff.

Warum brauchen wir instrumentelle UnterstĂŒtzung fĂŒr die Paginierung auf Tasten?

In unserem Team stellt sich hĂ€ufig die Frage der Optimierung von Abfragen in einem DBMS. Sie möchten immer etwas schneller sein, kommen aber nicht immer mit durchdachten Indizes aus – Sie mĂŒssen nach Workarounds suchen. WĂ€hrend einer dieser StreifzĂŒge durch das Internet auf der Suche nach sinnvollen Optimierungen fĂŒr die Arbeit mit Datenbanken bin ich darauf gestoßen Marcus Wynands unendlich hilfreicher Blog, Autor von SQL Performance Explained. Dies ist die seltene Art von Blog, in der Sie alle Artikel hintereinander lesen können.

Ich wĂŒrde gerne einen kurzen Artikel von Marcus fĂŒr Sie ĂŒbersetzen. Es kann gewissermaßen als Manifest bezeichnet werden, das auf das alte, aber immer noch relevante Problem der Leistung der Offset-Operation gemĂ€ĂŸ dem SQL-Standard aufmerksam machen soll.

An einigen Stellen werde ich den Autor durch ErlĂ€uterungen und Kommentare ergĂ€nzen. Ich werde alle diese Orte mit „ca.“ bezeichnen. fĂŒr mehr Klarheit

Eine kurze EinfĂŒhrung

Ich denke, viele Leute wissen, wie problematisch und langsam die Arbeit mit der Seitenauswahl ĂŒber den Offset ist. Wussten Sie, dass es ganz einfach durch ein effizienteres Design ersetzt werden kann?

Das SchlĂŒsselwort offset weist die Datenbank also an, die ersten n DatensĂ€tze in der Anfrage zu ĂŒberspringen. Die Datenbank muss jedoch weiterhin diese ersten n DatensĂ€tze in der angegebenen Reihenfolge von der Festplatte lesen (Hinweis: Sortierung anwenden, falls angegeben), und erst dann ist es möglich, DatensĂ€tze ab n+1 zurĂŒckzugeben. Das Interessanteste ist, dass das Problem nicht in der konkreten Implementierung im DBMS liegt, sondern in der ursprĂŒnglichen Definition gemĂ€ĂŸ Standard:


die Zeilen werden zunÀchst nach sortiert und dann durch Weglassen der in der angegebenen Anzahl von Zeilen begrenzt von Anfang an

-SQL:2016, Teil 2, 4.15.3 Abgeleitete Tabellen (Hinweis: derzeit der am hÀufigsten verwendete Standard)

Der entscheidende Punkt hierbei ist, dass Offset einen einzigen Parameter benötigt – die Anzahl der zu ĂŒberspringenden DatensĂ€tze, und das war’s. Nach dieser Definition kann das DBMS nur alle DatensĂ€tze abrufen und dann die unnötigen verwerfen. Offensichtlich zwingt uns diese Definition des Offsets zu zusĂ€tzlicher Arbeit. Dabei spielt es keine Rolle, ob es sich um SQL oder NoSQL handelt.

Nur ein bisschen mehr Schmerzen

Die Probleme mit dem Offset enden hier nicht, und hier erfahren Sie, warum. Was passiert in diesem Fall, wenn zwischen dem Lesen zweier Datenseiten von der Festplatte ein anderer Vorgang einen neuen Datensatz einfĂŒgt?

Warum brauchen wir instrumentelle UnterstĂŒtzung fĂŒr die Paginierung auf Tasten?

Wenn Offset verwendet wird, um DatensĂ€tze von vorherigen Seiten zu ĂŒberspringen, werden Sie beim HinzufĂŒgen eines neuen Datensatzes zwischen LesevorgĂ€ngen verschiedener Seiten höchstwahrscheinlich Duplikate erhalten (Hinweis: Dies ist möglich, wenn wir Seite fĂŒr Seite mit dem Order-by-Konstrukt lesen in der Mitte unserer Ausgabe könnte es einen neuen Eintrag geben).

Die Abbildung verdeutlicht diese Situation deutlich. Die Basis liest die ersten 10 DatensĂ€tze, danach wird ein neuer Datensatz eingefĂŒgt, der alle gelesenen DatensĂ€tze um 1 versetzt. Dann nimmt die Basis eine neue Seite aus den nĂ€chsten 10 DatensĂ€tzen und beginnt nicht wie vorgesehen mit dem 11., sondern mit dem 10., Duplizieren dieses Datensatzes. Es gibt noch andere Anomalien im Zusammenhang mit der Verwendung dieses Ausdrucks, aber dieser kommt am hĂ€ufigsten vor.

Wie wir bereits herausgefunden haben, handelt es sich hierbei nicht um Probleme eines bestimmten DBMS oder seiner Implementierungen. Das Problem besteht darin, die Paginierung gemĂ€ĂŸ dem SQL-Standard zu definieren. Wir teilen dem DBMS mit, welche Seite abgerufen oder wie viele DatensĂ€tze ĂŒbersprungen werden sollen. Die Datenbank ist einfach nicht in der Lage, eine solche Anfrage zu optimieren, da hierfĂŒr zu wenig Informationen vorhanden sind.

Es sollte auch klargestellt werden, dass es sich hierbei nicht um ein Problem mit einem bestimmten SchlĂŒsselwort handelt, sondern vielmehr um die Semantik der Abfrage. Es gibt mehrere weitere Syntaxen, die in ihrer Problematik identisch sind:

  • Das SchlĂŒsselwort offset ist wie bereits erwĂ€hnt.
  • Eine Konstruktion aus zwei SchlĂŒsselwörtern limit [offset] (obwohl limit selbst nicht so schlecht ist).
  • Filtern nach Untergrenzen, basierend auf der Zeilennummerierung (z. B. row_number(), rownum usw.).

Alle diese AusdrĂŒcke sagen Ihnen lediglich, wie viele Zeilen Sie ĂŒberspringen mĂŒssen, ohne zusĂ€tzliche Informationen oder Kontext.

SpĂ€ter in diesem Artikel wird das SchlĂŒsselwort offset als Zusammenfassung all dieser Optionen verwendet.

Leben ohne OFFSET

Stellen wir uns nun vor, wie unsere Welt ohne all diese Probleme aussehen wĂŒrde. Es stellt sich heraus, dass das Leben ohne Offset nicht so schwierig ist: Mit einer Auswahl können Sie nur die Zeilen auswĂ€hlen, die wir noch nicht gesehen haben (Hinweis: diejenigen, die nicht auf der vorherigen Seite waren), indem Sie eine Bedingung in where verwenden.

In diesem Fall gehen wir davon aus, dass Auswahlen auf einer geordneten Menge (gute alte Reihenfolge nach) ausgefĂŒhrt werden. Da wir eine geordnete Menge haben, können wir einen ziemlich einfachen Filter verwenden, um nur die Daten zu erhalten, die hinter dem letzten Datensatz der vorherigen Seite liegen:

    SELECT ...
    FROM ...
    WHERE ...
    AND id < ?last_seen_id
    ORDER BY id DESC
    FETCH FIRST 10 ROWS ONLY

Das ist das ganze Prinzip dieses Ansatzes. NatĂŒrlich macht es mehr Spaß, wenn man nach vielen Spalten sortiert, aber die Idee ist immer noch dieselbe. Es ist wichtig zu beachten, dass dieses Design auf viele anwendbar ist NoSQL-Entscheidungen.

Dieser Ansatz wird als Suchmethode oder Keyset-Paginierung bezeichnet. Es löst das Problem des schwebenden Ergebnisses (Hinweis: die zuvor beschriebene Situation beim Schreiben zwischen SeitenlesevorgĂ€ngen) und arbeitet natĂŒrlich, was wir alle lieben, schneller und stabiler als der klassische Offset. StabilitĂ€t liegt darin, dass die Bearbeitungszeit der Anfrage nicht proportional zur Anzahl der angeforderten Tabellen zunimmt (Hinweis: Wenn Sie mehr ĂŒber die Arbeit verschiedener AnsĂ€tze zur Paginierung erfahren möchten, können Sie dies tun Schauen Sie sich die PrĂ€sentation des Autors an. Dort finden Sie auch vergleichende Benchmarks fĂŒr verschiedene Methoden.

Eine der Folien spricht darĂŒberdass die Paginierung nach Tasten natĂŒrlich nicht allmĂ€chtig ist – sie hat ihre Grenzen. Das Wichtigste ist, dass sie nicht in der Lage ist, zufĂ€llige Seiten zu lesen (Hinweis: inkonsistent). Im Zeitalter des endlosen Scrollens (Anmerkung: im Frontend) ist dies jedoch kein so großes Problem. Die Angabe einer Seitenzahl zum Anklicken ist im UI-Design ohnehin eine schlechte Entscheidung (Anmerkung: Meinung des Autors des Artikels).

Was ist mit den Werkzeugen?

Die Paginierung auf Tasten ist oft nicht geeignet, da diese Methode nicht instrumental unterstĂŒtzt wird. Bei den meisten Entwicklungstools, einschließlich verschiedener Frameworks, können Sie nicht genau auswĂ€hlen, wie die Paginierung durchgefĂŒhrt werden soll.

Erschwerend kommt hinzu, dass die beschriebene Methode eine durchgĂ€ngige UnterstĂŒtzung der eingesetzten Technologien erfordert – vom DBMS bis zur AusfĂŒhrung einer AJAX-Anfrage im Browser mit endlosem Scrollen. Anstatt nur die Seitenzahl anzugeben, mĂŒssen Sie jetzt einen SchlĂŒsselsatz fĂŒr alle Seiten gleichzeitig angeben.

Allerdings wĂ€chst die Zahl der Frameworks, die die Paginierung auf SchlĂŒsseln unterstĂŒtzen, allmĂ€hlich. Folgendes haben wir im Moment:

(Hinweis: Einige Links wurden entfernt, da zum Zeitpunkt der Übersetzung einige Bibliotheken seit 2017–2018 nicht mehr aktualisiert waren. Bei Interesse können Sie sich die Originalquelle ansehen.)

In diesem Moment wird Ihre Hilfe benötigt. Wenn Sie ein Framework entwickeln oder unterstĂŒtzen, das die Paginierung in irgendeiner Weise nutzt, dann bitte ich Sie, ich fordere Sie auf, ich flehe Sie an, native UnterstĂŒtzung fĂŒr die Paginierung auf Tasten bereitzustellen. Wenn Sie Fragen haben oder Hilfe benötigen, helfe ich Ihnen gerne weiter (Forum, Twitter, Kontakt Formular) (Anmerkung: Aus meiner Erfahrung mit Marcus kann ich sagen, dass er wirklich begeistert davon ist, dieses Thema zu verbreiten.)

Wenn Sie vorgefertigte Lösungen verwenden, die Ihrer Meinung nach UnterstĂŒtzung fĂŒr die Paginierung nach SchlĂŒsseln wert sind, erstellen Sie eine Anfrage oder bieten Sie nach Möglichkeit sogar eine vorgefertigte Lösung an. Sie können auch auf diesen Artikel verlinken.

Fazit

Der Grund dafĂŒr, dass ein so einfacher und nĂŒtzlicher Ansatz wie die Paginierung nach SchlĂŒsseln nicht weit verbreitet ist, liegt nicht darin, dass er technisch schwierig umzusetzen ist oder großen Aufwand erfordert. Der Hauptgrund dafĂŒr ist, dass viele es gewohnt sind, Offset zu sehen und damit zu arbeiten – dieser Ansatz wird durch die Norm selbst vorgegeben.

Infolgedessen denken nur wenige Menschen darĂŒber nach, den Ansatz zur Paginierung zu Ă€ndern, und aus diesem Grund entwickelt sich die instrumentelle UnterstĂŒtzung durch Frameworks und Bibliotheken nur unzureichend. Wenn Ihnen die Idee und das Ziel der versatzfreien Paginierung am Herzen liegen, helfen Sie mit, sie zu verbreiten!

Source: https://use-the-index-luke.com/no-offset
Autor: Markus Winand

Source: habr.com

Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz und VPS-VDS-Servern đŸ”„ Kaufen Sie zuverlĂ€ssiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server | ProHoster