Datenstruktur, die effiziente tagbasierte Suchvorgänge ermöglicht

11

Ich suche eine hocheffiziente Datenstruktur zur Speicherung von Daten ähnlich der folgenden.

ID Tags Order1 Order2 
--------------------------
1 1,2 1 1
2 2,5 2 3
3 1,7 4 7
4 6 3 0

Ich muss in der Lage sein, diese Struktur so abzufragen, dass ich eine Liste aller IDs bekomme, die einen Ausdruck von Tags enthalten - unterstützende ANDund ORund NOTOperationen. Z.B. ((1 oder 2) und nicht 7)

Ich muss auch in der Lage sein, die Reihenfolge der Ergebnisse (Reihenfolge1 oder Reihenfolge2) anzugeben und die maximalen Zeilen anzugeben, die mit einem optionalen Versatz zurückgegeben werden. Die Leistung für den Abruf der ersten 30-100 Ergebnisse ist der Schlüssel.

Schließlich brauche ich eine kostengünstige Möglichkeit, um nach "Tag-Beziehungen" zu suchen. Ich möchte beispielsweise wissen, welche Tags sich auf Tags (1 ODER 2) beziehen und in welcher Häufigkeit. Dies bedeutet, welche Tags im selben Satz wie 1 ODER 2 ... nach Häufigkeit geordnet erscheinen.

Gibt es eine Vorstellung davon, welche Datenstruktur (oder welcher Satz von Strukturen) für diese Art von Arbeit hocheffizient wäre?

(Ich möchte dies als Proof of Concept für die Neugestaltung der markierten Seiten der SE-Site-Familie verwenden.)

Sam Safran
quelle
1
Nur ein Kommentar (vielleicht trivial). Warum verlassen Sie sich nicht auf ein relationales Datenbankverwaltungssystem? Sie können eine Tabelle mit den Paaren <id, tag> definieren und einen Index für die Tag-Spalte hinzufügen. Anschließend können Sie Standard-SQL-Abfragen zum Extrahieren von Daten verwenden. Das RDBMS erledigt effizient die "schmutzige" Arbeit der Abfrageoptimierung und Ausgabesortierung.
Marzio De Biasi
@Vor, die Ausdrücke sind im hohen Maßstab unglaublich ineffizient, die Selbstverbindungen werden zu albtraumhaften Abfragen.
Sam Saffron
@ Sam: ok. Ihre Aufgabe ist ziemlich häufig, daher dachte ich, dass ein gutes RDBMS (mit einem Data Mining-Tool) die Aufgabe übernehmen könnte. Ich überlasse das Wort einem Datenstruktur-Experten. :-)
Marzio De Biasi
Ich glaube, dass das Zulassen aller Kombinationen von AND, OR, NOT es schwierig machen wird, eine Datenstruktur zu erstellen, die nicht alle Elemente auflistet (möglicherweise könnte sie auf 3-CNF beschränkt sein?). Wenn keine solche Einschränkung besteht, durchlaufen Sie möglicherweise einfach die Datensätze (in der angegebenen Reihenfolge), bis Sie 30-100 finden, die Ihre Tag-Anforderungen erfüllen. Obwohl ich im Allgemeinen dem Vorschlag von Vor zustimme, eine Datenbank zu verwenden, um das schwere Heben für Sie zu erledigen.
Bbejot
Kein Experte, aber ich denke, wenn Sie die Art und Weise, wie Sie nach Tags fragen können, nicht einschränken, wird es schwierig. Die Beschränkung auf CNFs (wie von bbejot vorgeschlagen) ist eine Möglichkeit, eine andere die Anzahl der verschiedenen Tags, nach denen die Abfrage fragen kann, um eine kleine Anzahl (z. B. 6).
Kaveh

Antworten:

6

Dies ist nicht gerade eine Antwort auf eine effiziente Datenstruktur, sondern eine Ausarbeitung der Kommentare von @bbejot und @Kaveh, die ein handwedelndes Argument dafür liefern, warum wir angesichts der aktuellen Frage nicht etwas erwarten sollten, das viel besser funktioniert als das Durchsuchen der ganze Datenbank. Das Argument basiert auf einer Reduktion von SAT, der exponentiellen Zeithypothese und viel Handwinken.

Angenommen, wir haben bis zu verschiedene Tags, dann können wir uns vorstellen , dass jede ID einem Bitvektor der Länge wobei wenn wir das te Tag haben, und sonst. Da es keine wirklichen Einschränkungen für das Aussehen der Datenbank gibt, kann ich davon ausgehen, dass sie die IDs bis wobei der ten ID ein binärer Tag-Vektor von . Die Auftragsfelder können beliebig sein, da sie das Problem nur erschweren. Nun, wenn wir eine willkürliche Abfrage von , undnx|x|=nxj=1jxj=012nkkANDORNOTs dann stellt dies nur eine SAT-Frage zu Variablen. Nach der exponentiellen Zeithypothese können wir nicht erwarten, dass dies viel schneller als ... oder mit anderen Worten, wir können nicht erwarten, dass dies viel schneller ist als das Durchsuchen der gesamten Datenbank.n2n

Wir sollten keine effiziente Suche in der Länge der Abfrage erwarten (durch Reduktion auf SAT). Wir sollten auch nicht viel besseres erwarten, als alle Elemente in der Datenbank anhand der exponentiellen Zeithypothese zu betrachten.

Um auf eine effiziente Datenstruktur für diese Frage zu hoffen, müssen wir einige ernsthafte Annahmen über die Struktur der Datenbank treffen, die in dieser Frage nicht getroffen werden. Wenn wir beispielsweise eine spezielle Struktur für die Abfragen annehmen (z. B. CNF), können wir auf etwas Effizienteres hoffen. Eine alternative Annahme betrifft die Struktur der Datenbank. Wir könnten wahrscheinlich annehmen, dass bei Tags nur ein kleiner Teil der Tags auf einer bestimmten ID vorhanden ist (sagen wir logarithmisch einige s). Dies ist angesichts der Anwendung von getaggten Fragen keine unangemessene Annahme (was nützen Tags, wenn fast jedes einzelne Tag für eine Frage verwendet wird).n1

Artem Kaznatcheev
quelle
Gute Beobachtung. Jede Frage hat höchstens 5 Tags, sodass eine Abfrage nach Tags einem 5-CNF entspricht.
Kaveh
Danke! Ja, wir können hier weiter von 5-CNF ausgehen, das Tagging-Verhalten ist nicht zufällig. Im Allgemeinen markieren die Benutzer Inhalte mit den am häufigsten verwendeten Tags, sodass einige andere Verknüpfungen möglich sind.
Sam Saffron
1
@Kaveh, am Ende haben wir eine In-Memory-Struktur gerollt. Es gibt einige nicht triviale Verknüpfungen. Die Sortierung ist ein Engpass. Wenn Sie die Heap-Sortierung oder eine modifizierte schnelle Sortierung verwenden, können Sie Top-N effizient auswählen, ohne eine vollständige Sortierung durchführen zu müssen. Durch die Vorberechnung von Sortierungen können Sie Pivots effizienter auswählen und Sortierungen vermeiden, wenn ein vollständiger Scan erforderlich ist. Multithreading beschleunigt die Auswahl. Es kann viel Arbeit in den Hintergrund verschoben werden, bevor Benutzer mit den Strukturen interagieren. Erstaunlicherweise haben unsere In-Memory-Strukturen einen Durchschnitt von 0 ms für eine Suche im Stapelüberlauf-Datensatz.
Sam Saffron
@SamSaffron - Wo ist der MSO-Beitrag, in dem diese Funktion detailliert beschrieben wird? Wir haben einen Fehlerbericht bekommen hier .
Kevin Vermeer
5

Dies ist eine ziemlich einfache Antwort, aber ich denke effektiv:

Ein suggestiver Typ für Ihre Datenstruktur: Map Tag ([Id],[Id])Hier werden die beiden ID- Listen nach Reihenfolge1 bzw. Reihenfolge2 sortiert. Das Verwalten und Generieren dieser Struktur ist mit Kosten verbunden, aber Abfragen für ein einzelnes Tag sollten in der Anzahl der Tags . Das Speichern der Länge der Listen mit den Listen würde bei der Abfrageoptimierung helfen, und viel besser als eine tatsächliche Liste wäre ein fauler Bitvektor, der die Negation ebenfalls extrem billig machen würde.O(log(n))

Wenn Sie eine andere Karte des Typs Map Id (Set Tag)einwerfen, sollte die Erzeugung der zugehörigen Frequenzen bei einer Liste von Ids in der Größe der Liste und der Größe der Sätze von Tags sein.O(nlog(m))

sclv
quelle
Ich stimme eher zu, dass einige sehr einfache Strukturen wie eine mehrfach gespulte Karte der beste Weg sind, um hierher zu gelangen. Speicher ist billig und das Verwalten mehrerer Caches ist nicht zu schwierig
Sam Saffron