Genaue Paginierung mit linken Joins

7

Ich habe eine Weile darüber nachgedacht und es ist zu einem Punkt gekommen, an dem es besser ist, herum zu fragen und zuzuhören, was andere Leute denken.

Ich baue ein System auf, das Standorte auf Mysql speichert. Jeder Standort hat einen Typ und einige Standorte haben mehrere Adressen.

Die Tabellen sehen ungefähr so ​​aus

%Vor%

Also, wenn ich die Datenbank nach den zuletzt hinzugefügten 10 abfragen wollte, würde ich mit so etwas gehen:

%Vor%

Richtig? Aber das Problem ist, dass, wenn ein Ort mehr als 1 Adresse hat, das Limit / Paginierung wird nicht accurrate, es sei denn, ich "GROUP BY l.location_id", aber das wird nur eine Adresse für jeden Ort zeigen .. was passiert mit den Orten, die mehrere Adressen haben?

Also dachte ich, der einzige Weg, dies zu lösen, besteht darin, eine Abfrage innerhalb einer Schleife durchzuführen. So etwas (Pseudocode):

%Vor%

Jetzt bekomme ich die letzten 10 Plätze, aber dadurch komme ich mit mindestens 10 weiteren Anfragen, und ich denke nicht, dass das der App-Leistung hilft.

Gibt es einen besseren Weg, um das zu erreichen, wonach ich suche? (genaue Paginierung).

    
mpratt 14.02.2012, 19:19
quelle

4 Antworten

17

Hier ist Ihre ursprüngliche Abfrage

%Vor%

Sie führen die Seitennummerierung zuletzt durch. Wenn Sie diese Abfrage umstrukturieren, können Sie die Seitennumerierung früher durchführen.

%Vor%

Beachten Sie, dass ich eine Unterabfrage mit dem Namen k erstellt habe. Die 10 Schlüssel werden abgeholt und ZUERST bestellt !!!

Dann können die JOINs von dort weitergehen, hoffentlich mit nur 10 location_ids.

Was die Unterabfrage k unterstützt, ist ein Index, der location_id und location_type_id

enthält %Vor%

Hier ist etwas, das Ihnen an diesem Ansatz gefallen könnte

Wie fragen Sie nach den nächsten 10 IDs (IDs 11 - 20)? So:

%Vor%

Alles, was Sie tun müssen, ist die LIMIT -Klausel in der Unterabfrage k mit jeder neuen Seite zu ändern.

  • LIMIT 20,10
  • LIMIT 30,10
  • und so weiter ...

Ich kann das Refactoring verbessern, indem ich die Standorttabelle entferne und die Unterabfrage k die erforderlichen Felder wie folgt tragen lasse:

%Vor%

Dieser zusätzliche Index wäre für diese Version nicht notwendig.

Probieren Sie es aus !!!

    
RolandoMySQLDBA 14.02.2012, 19:49
quelle
3

besser als Schleife und 10 Abfragen, könnten Sie für die Position.location_id Grenze 10 für die Seitenumbruch abfragen, verketten Sie das in eine durch Komma getrennte Zeichenfolge und dann die vollständige Abfrage, um WHERE location.location_id IN (1,2,3...{list of ids})

zu bekommen     
Jonathan Kuhn 14.02.2012 19:26
quelle
3

Sie könnten mit Ihrem ursprünglichen Gedanken zur Gruppierung nach der location_id gehen und dann die Funktion group_concat verwenden, um alle Adressen für diesen Ort als 1 Feld anzuzeigen.

%Vor%     
Jared 14.02.2012 19:30
quelle
2

Es gibt einige Möglichkeiten, dies zu lösen:

  • Sie könnten der IsPrimary -Tabelle eine location_information -Bitspalte hinzufügen und einen Trigger hinzufügen, um sicherzustellen, dass jeder Speicherort immer nur einen location_information -Datensatz hat, wobei dieser Wert auf 1 gesetzt ist.
  • Sie können den ältesten oder neuesten Datensatz location_information (MIN / MAX) auswählen, indem Sie die Spalte location_id verwenden, wenn Sie keine Spalten DateCreated oder DateModified haben.
RedFilter 14.02.2012 19:21
quelle

Tags und Links