Ich möchte benutzerdefinierte Tags für Benutzerkäufe bei jeder Transaktion speichern. Wenn Benutzer beispielsweise Schuhe gekauft haben, sind dies Tags "SPORTS", "NIKE", SHOES, COLOUR_BLACK, SIZE_12,..
Diese Tags sind diejenigen Verkäufer, die daran interessiert sind, eine Anfrage zu stellen, um die Verkäufe zu verstehen.
Meine Idee ist, wann immer ein neues Tag hereinkommt, neuen Code (so etwas wie Hashcode, aber sequentiell) für dieses Tag zu erstellen, und der Code beginnt mit "a-z"
26 Buchstaben und "aa, ab, ac...zz"
geht dann weiter. Behalten Sie nun alle in einer Transaktion angegebenen Tags in der einen Spalte, die tag (varchar)
durch Trennen mit aufgerufen wird "|"
.
Nehmen wir an, Mapping ist (auf Anwendungsebene)
"SPORTS" = a
"TENNIS" = b
"CRICKET" = c
...
...
"NIKE" = z //Brands company
"ADIDAS" = aa
"WOODLAND" = ab
...
...
SHOES = ay
...
...
COLOUR_BLACK = bc
COLOUR_RED = bd
COLOUR_BLUE = be
...
SIZE_12 = cq
...
Wenn Sie also die oben genannte Kauftransaktion speichern, tag="|a|z|ay|bc|cq|"
sieht das Tag wie folgt aus. Jetzt kann der Verkäufer die Anzahl der verkauften SCHUHE suchen, indem er die WHERE
Bedingung hinzufügt tag LIKE %|ay|%
. Jetzt ist das Problem, dass ich keinen Index (Sortierschlüssel in Rotverschiebungsdatenbank) für "LIKE beginnt mit%" verwenden kann. Wie kann man dieses Problem lösen, da ich möglicherweise 100 Millionen Datensätze habe? Ich möchte keinen vollständigen Tabellenscan.
Gibt es eine Lösung, um dies zu beheben?
Update_1: Ich habe das bridge table
Konzept (Querverweistabelle) nicht befolgt, da ich nach dem Durchsuchen der angegebenen Tags eine Gruppierung der Ergebnisse durchführen möchte. Meine Lösung gibt nur eine Zeile an, wenn zwei Tags in einer einzigen Transaktion übereinstimmen, aber die Brückentabelle gibt mir zwei Zeilen? dann wird meine Summe () verdoppelt.
Ich habe einen Vorschlag wie unten
EXISTS (SELECT 1 FROM transaction_tag WHERE tag_id = 'zz' und trans_id = tr.trans_id) in der WHERE-Klausel einmal für jedes Tag (Hinweis: Es wird davon ausgegangen, dass tr ein Alias für die Transaktionstabelle in der umgebenden Abfrage ist).
Ich bin dem nicht gefolgt; da ich AND- und OR-Bedingungen für die Tags ausführen muss, Beispiel ("SPORTS" UND "ADIDAS") ---- "SHOE" AND ("NIKE" ODER "ADIDAS")
Update_2: Ich bin dem Bitfeld nicht gefolgt, da ich nicht weiß, dass Redshift diese Unterstützung bietet. Ich gehe auch davon aus, dass mein System mindestens 3500 Tags haben wird, und ordne jedem ein Bit zu. Dies ergibt 437 Bytes für jede Transaktion, obwohl für eine Transaktion nur maximal 5 Tags angegeben werden können. Irgendeine Optimierung hier?
Lösung_1:
Ich habe darüber nachgedacht, min (SMALL_INT) und max value (SMALL_INT) zusammen mit der Tags-Spalte hinzuzufügen und darauf einen Index anzuwenden.
so etwas wie das
"SPORTS" = a = 1
"TENNIS" = b = 2
"CRICKET" = c = 3
...
...
"NIKE" = z = 26
"ADIDAS" = aa = 27
Meine Spaltenwerte sind also
`tag="|a|z|ay|bc|cq|"` //sorted?
`minTag=1`
`maxTag=95` //for cq
Und Abfrage für die Suche Schuh (ay = 51) ist
maxTag <= 51 AND tag LIKE %|ay|%
Und die Abfrage für die Suche nach Schuh (ay = 51) UND SIZE_12 (cq = 95) ist
minTag >= 51 AND maxTag <= 95 AND tag LIKE %|ay|%|cq|%
Wird dies einen Nutzen bringen? Bitte schlagen Sie Alternativen vor.
INNER JOIN
zu transaction_tag
einmal für jeden Tag angefordert oder unter Verwendung von EXISTS (SELECT 1 FROM transaction_tag WHERE tag_id = 'zz' and trans_id = tr.trans_id)
in der WHERE
einmal Klausel für jeden Tag (Hinweis: nimmt an tr ein Alias für das ist transaction
Tabelle in der umgebenden Abfrage).
transaction_tag
Tabelle betrachtet, die verknüpft isttransaction
undtag
in einer Viele-zu-Viele-Beziehung steht? In Bezug auf die Leistung ist es in der Regel eine schlechte Idee, mehrere Werte als einfach begrenzten Text in einer einzelnen Spalte zu speichern.