2013-02-27 7 views
10

So habe ich eine Tabelle der Benutzer Favoriten. Es gibt ein paar Millionen Reihen von ihnen.Effiziente Möglichkeit, umorderbare Artikel in einer Datenbank zu speichern

Derzeit haben sie nur drei Spalten: id (pk), userId und someFkRef. Es gibt einen Index für userId, damit ich die Favoriten eines Benutzers schnell auswählen kann.

Derzeit sind diese von id bestellt, die effektiv nur die Reihenfolge ist. Wir möchten dem Benutzer eine Chance bieten, seine Favoriten neu zu ordnen, am ehesten durch eine Art Drag & Drop-Interaktion.

Meine erste (und ich vermute, naiv) Ansatz zu diesem wäre einfach eine order Spalte und einen zusammengesetzten Index über userId, order hinzuzufügen. Wenn jedoch der Benutzer nach der Reflektion seinen Artikel in einiger Entfernung über die Liste bewegt, müssen alle Zwischenzeilen zwischen der Startposition und der Endposition des Artikels ihre order Spalte neu berechnen und daher auch den Index.

Dies ist (höchstwahrscheinlich) schlecht.

Bevor ich lange versuche, genau zu quantifizieren, wie schlecht, frage ich mich, ob es eine bessere Tabelle-basierte Darstellung gibt, die mit den oben beschriebenen Arten von Operationen billiger zu manipulieren ist.

+0

Ich bin nicht davon überzeugt, dass Sie das neue Feld indizieren müssen. –

+0

Im Allgemeinen erfordert 'order by' ops einen Index, nein? – spender

+0

@spender Benötigen Sie Nein, aber wenn Ihre Tabellenzeilen groß sind und Sie eine große Ergebnismenge erhalten, kann die Sortierung mit Hilfe eines Indexes ein wenig weniger E/A generieren. –

Antwort

3

Wenn Sie nicht in der Lage sein müssen, someFkRef über mehrere Benutzer hinweg zu manipulieren (beispielsweise um die Liste der Benutzer zu erhalten), dann könnte nur ein Datensatz pro Benutzer mit einer geordneten Liste von someFkRef (refA , refB).

Aber es ist eine Form der De-Normalisierung, und da es einige Nachteile hat, es hängt wirklich von Ihren Bedürfnissen (und Ihre zukünftigen Bedürfnisse, das heißt, wo die Mühe kommt)

+0

Ja, Denormalisierung wird Sie treffen, selbst wenn es derselbe Benutzer ist: a) Sie müssen eine große Liste begrenzen/versetzen und manipulieren; b) diese Daten werden über das Internet übertragen und der Benutzer sortiert schnell eine Liste von hundert Elementen (Hallo, O (N), Verzögerungen und Desynchronisation). Denormalisierung ist ein großer Schmerz und niemand sollte das jemals tun wollen. –

6

Für eine Drag & Drop-Interaktion, Die bessere Wette ist eine Priorität. Sie würden mit den Prioritäten 1, 2, 3 usw. beginnen, genau wie eine Sortierreihenfolge.

Aber dann möchte der Benutzer Artikel 5 zwischen 1 und 2 bewegen. Voila! Gib ihm den Wert 1,5. Keine anderen Werte müssen geändert werden. Das Index-Update erledigt den Rest.

Damit dies funktioniert, muss die Priorität als Fließkommazahl gespeichert werden. Das könnte ein Problem sein. Außerdem könnte eine ausreichend große Anzahl von Änderungen dazu führen, dass die Grenzen des Gleitkomma-Punktes überschritten werden. Also, wenn ein Benutzer versucht, das letzte Element zu nehmen und es zwischen die ersten beiden zu setzen, kann er/sie damit etwa ein paar Dutzend Male oder so durchkommen.

Sie können dieses Problem beheben mit einem Prozess, der bei der Startnummer für einen (oder alle Benutzer, wenn im Batch) 1.

+0

Dies ist auch ein wertvoller Ansatz. Aber Sie müssen immer noch einen Index für die Spalte someFkRef haben, so dass es immer noch ein bisschen aufwendig ist, ist die Tabelle sehr groß. –

+1

@SamuelEUSTACHI Index ist nicht der schlechteste Teil. Der schlimmste Teil ist, dass Fließkommazahlen eine endliche Genauigkeit haben und nach etwa 53 gut durchdachten Bewegungen kann man die Ordnungslogik durchbrechen. Ja, Sie können immer einen Zähler und einen Auslöser haben, um diese Liste zu renormieren, aber ich bin mir ziemlich unsicher, ob es überhaupt eine effizientere Lösung sein wird. –

1

nicht sicher, was Ihre abhängigen Referenzen könnten es sein, das ID-Feld, in regelmäßigen Abständen neu zuweist, aber haben Sie dachte darüber nach, es zu überschreiben? Ich denke, es gibt eine SET IDENTITY INSERT = ON, oder etwas, das Sie tun können.

Mir ist klar, dass dies eine seltsame Sache ist, aber wenn man bedenkt, was man versucht zu tun, kann es Sinn machen und den geringsten Overhead verursachen.

+0

@Joachim - Renumber recordcount = 2 - nur der Spender und der Empfänger. Reindex ist unbestimmt - vermutlich hat er eine eingebaute Padding-Funktion, und mit Millionen von Datensätzen wird er vermutlich außerhalb des Spitzenwerts neu indiziert. – Chains

Verwandte Themen