sql - nicht - relationale datenbank vorteile




Stellen Sie die Bestellung in einer relationalen Datenbank dar (7)

Ich habe eine Sammlung von Objekten in einer Datenbank. Bilder in einer Fotogalerie, Produkte in einem Katalog, Kapitel in einem Buch usw. Jedes Objekt wird als eine Reihe dargestellt. Ich möchte in der Lage sein, diese Bilder beliebig zu ordnen und diese Reihenfolge in der Datenbank zu speichern. Wenn ich die Objekte zeige, sind sie in der richtigen Reihenfolge.

Nehmen wir zum Beispiel an, ich schreibe ein Buch, und jedes Kapitel ist ein Objekt. Ich schreibe mein Buch und lege die Kapitel in folgender Reihenfolge:

Einführung, Zugänglichkeit, Form und Funktion, Fehler, Konsistenz, Schlussfolgerung, Index

Es geht an den Editor und kommt mit der folgenden vorgeschlagenen Reihenfolge zurück:

Einführung, Form, Funktion, Zugänglichkeit, Konsistenz, Fehler, Schlussfolgerung, Index

Wie kann ich diese Bestellung robust und effizient in der Datenbank speichern?

Ich hatte die folgenden Ideen, aber ich bin nicht begeistert von ihnen:

  1. Array. Jede Zeile hat eine Bestell-ID. Wenn die Bestellung geändert wird (über eine Entnahme gefolgt von einer Einfügung), werden die Bestell-IDs aktualisiert. Dies erleichtert die Suche, da es nur ORDER BY , aber es scheint einfach zu sein.

    // REMOVAL
    UPDATE ... SET orderingID=NULL WHERE orderingID=removedID
    UPDATE ... SET orderingID=orderingID-1 WHERE orderingID > removedID
    // INSERTION
    UPDATE ... SET orderingID=orderingID+1 WHERE orderingID > insertionID
    UPDATE ... SET orderID=insertionID WHERE ID=addedID

  2. Verknüpfte Liste Jede Zeile hat eine Spalte für die ID der nächsten Zeile in der Reihenfolge. Traversal scheint hier teuer zu sein, obwohl ich ORDER BY , an das ich nicht denke, irgendwie einsetzen kann.

  3. Platzierte Anordnung. Legen Sie die orderID (wie in # 1 verwendet) als groß fest, also ist das erste Objekt 100, das zweite ist 200 usw. Wenn eine Insertion stattfindet, legen Sie sie einfach auf (objectBefore + objectAfter)/2 . Natürlich müsste dies gelegentlich neu ausbalanciert werden, so dass Sie nicht zu nahe beieinander sind (selbst mit Floats würden Sie eventuell zu Rundungsfehlern kommen).

Keines von diesen scheint mir besonders elegant zu sein. Hat jemand einen besseren Weg, es zu tun?


Da ich mit Django hauptsächlich auf dieses Problem gestoßen bin, habe ich festgestellt, dass diese Lösung am effektivsten ist. Es scheint, dass es keinen "richtigen Weg" gibt, dies in einer relationalen Datenbank zu tun.


Das Mischen von acts_as_list in Rails behandelt dies im Prinzip wie in 1. beschrieben. Es sucht nach einer INTEGER-Spalte namens position (von der Sie natürlich den Namen überschreiben können) und verwendet diese, um ORDER BY auszuführen. Wenn Sie Dinge neu ordnen möchten, aktualisieren Sie die Positionen. Es hat mir jedes Mal gut gedient, wenn ich es benutzt habe.

Als eine Randnotiz können Sie die Notwendigkeit entfernen, immer auf INSERTS / DELETES zu repositionieren, indem Sie eine spärliche Nummerierung verwenden - so wie eine einfache zurück in den Tag ... Sie können Ihre Positionen 10, 20, 30 usw. nummerieren. und wenn Sie etwas zwischen 10 und 20 einfügen müssen, fügen Sie es einfach mit einer Position von 15 ein. Ebenso können Sie beim Löschen einfach die Zeile löschen und die Lücke verlassen. Sie müssen nur dann neu nummerieren, wenn Sie die Bestellung tatsächlich ändern oder wenn Sie versuchen, eine Beilage zu erstellen, und es gibt keine geeignete Lücke zum Einfügen.

Abhängig von Ihrer speziellen Situation (z. B. ob Sie die anderen Zeilen bereits in den Speicher geladen haben oder nicht) ist es sinnvoll oder nicht sinnvoll, den Lücken-Ansatz zu verwenden.


Ich habe das in meinem letzten Projekt gemacht, aber es war für einen Tisch, der nur gelegentlich speziell bestellt werden musste und nicht zu oft aufgerufen wurde. Ich denke, dass die Anordnung mit Abstand die beste Option wäre, da eine Umordnung im Durchschnitt am billigsten wäre, da nur eine Änderung an einem Wert und eine Abfrage an zwei vorgenommen wird.

Außerdem würde ich mir vorstellen, dass ORDER BY von Datenbankanbietern ziemlich stark optimiert würde, sodass die Nutzung dieser Funktion für die Leistung im Gegensatz zur Implementierung der verknüpften Liste vorteilhaft wäre.


Ich hatte das gleiche Problem und habe wahrscheinlich mindestens eine Woche damit verbracht, mich mit der richtigen Datenmodellierung zu befassen, aber ich glaube, ich habe es endlich verstanden. Unter Verwendung des Array-Datentyps in PostgreSQL können Sie den Primärschlüssel jedes bestellten Artikels speichern und das Array entsprechend aktualisieren, indem Sie Änderungen oder Löschungen vornehmen, wenn sich Ihre Bestellung ändert. Wenn Sie auf eine einzelne Zeile verweisen, können Sie alle Ihre Objekte basierend auf der Reihenfolge in der Arrayspalte zuordnen.

Es ist immer noch ein bisschen abgehackt von einer Lösung, aber es wird wahrscheinlich besser als Option 1 funktionieren, da Option 1 erfordert, die Bestellnummer aller anderen Zeilen bei Bestelländerungen zu aktualisieren.


Ich würde eine fortlaufende Nummer machen, mit einem Auslöser auf dem Tisch, der Platz für eine Priorität schafft, wenn sie bereits existiert.


Nur ein Gedanke, der die Option # 1 vs # 3 in Betracht zieht: verschiebt die Option mit dem beabstandeten Array (# 3) nur das Problem des normalen Arrays (# 1)? Egal welcher Algorithmus Sie wählen, entweder ist er kaputt, und Sie werden später mit # 3 Probleme bekommen, oder es funktioniert, und dann sollte # 1 genauso gut funktionieren.


Wenn die Objekte nicht stark von anderen Tabellen getastet werden und die Listen kurz sind, ist es am einfachsten, alles in der Domäne zu löschen und nur die korrekte Liste neu einzufügen. Aber das ist nicht praktisch, wenn die Listen groß sind und Sie viele Einschränkungen haben, um das Löschen zu verlangsamen. Ich denke deine erste Methode ist wirklich die sauberste. Wenn Sie es in einer Transaktion ausführen, können Sie sicher sein, dass nichts Ungewöhnliches passiert, während Sie sich in der Mitte des Updates befinden, um die Bestellung zu vermasseln.





django-models