2013-09-23 9 views
11

Ich versuche herauszufinden, wie das Schema für dieses ereignisbasierte Analysesystem, das ich schreibe, am besten modelliert werden kann. Mein Hauptanliegen ist es, dies auf eine Weise zu schreiben, die Abfragen einfach und schnell macht. Ich werde auch MySQL verwenden. Ich werde einige der Anforderungen besprechen und einen Überblick über ein mögliches (aber ich finde armes) Schema geben.Entwerfen des Datenbankschemas für ereignisbasierte Analysen

Anforderungen

  • Track-Ereignisse (zB Spur Vorkommen des "APP_LAUNCH" event)

  • benutzerdefinierte Ereignisse definieren

  • Fähigkeit zu segmentieren Ereignisse auf> 1 benutzerdefinierte Eigenschaften (zB get Vorkommen von "APP_LAUNCH", segmentiert in der Eigenschaft "APP_VERSION")

  • Track-Sitzungen

  • Abfragen durchführt, basierend auf Zeitstempel Bereich

Mögliche Modellierung

Das Hauptproblem, das ich habe, ist, wie die Segmentierung zu modellieren und die Abfragen, die Gesamtzahl eines Ereignisses zu erhalten auszuführen .

Meine ursprüngliche Idee war es, eine EVENTS-Tabelle mit einer ID, einem int count, einem timestamp, einer Eigenschaft (?) Und einem Fremdschlüssel für einen EVENTTYPE zu definieren. Ein EVENTTYPE hat eine ID, einen Namen und zusätzliche Informationen, die zu einem generischen Ereignistyp gehören. Das Ereignis "APP_LAUNCH" würde beispielsweise einen Eintrag in der Tabelle EVENTS mit einer eindeutigen ID haben, wobei count die Anzahl der aufgetretenen Ereignisse, den Zeitstempel (nicht sicher darüber, woran dies eingeprägt ist) und eine Eigenschaft oder angibt Liste von Eigenschaften (zB "APP_VERSION", "COUNTRY", etc.) und ein Fremdschlüssel zu einem EVENTTYPE mit dem Namen "APP_LAUNCH".

Kommentare und Fragen

Ich bin mir ziemlich sicher, dass dies dies aus den folgenden Gründen zu modellieren kein guter Weg ist. Es macht es schwierig, Zeitstempel-Fernabfragen durchzuführen ("Anzahl von APP_LAUNCHES zwischen Zeit x und y"). Die Tabelle EVENTTYPE erfüllt keinen Zweck. Schließlich bin ich unsicher, wie ich selbst Abfragen für verschiedene Segmentierungen durchführen würde. Der letzte ist derjenige, um den ich mich am meisten Sorgen mache.

Ich würde jede Hilfe bei helfen, dieses Modell korrekt zu modellieren oder mich auf Ressourcen verweisen, die helfen würden.

Eine letzte Frage (die wahrscheinlich dumm ist): Ist es schlecht, eine Zeile für jedes Ereignis einzufügen? Zum Beispiel, sagen meine Client-seitige Bibliothek den folgenden Aufruf an meine API macht:

track("APP_LAUNCH", {count: 4, segmentation: {"APP_VERSION": 1.0}}) 

Wie kann ich das tatsächlich speichere in der Tabelle (dies ist eng mit dem Schema-Design im Zusammenhang natürlich)? Ist es schlecht, einfach eine Zeile für jeden dieser Anrufe einzufügen, von denen es möglicherweise eine erhebliche Menge gibt? Meine Bauchreaktion ist, dass ich mich hauptsächlich für die aggregierten Gesamtzahlen interessiere. Ich habe nicht genug Erfahrung mit SQL, um zu wissen, wie diese Abfragen möglicherweise Hunderttausende dieser Einträge ausführen. Würde eine aggregierte Tabelle oder ein In-Memory-Cache dazu beitragen, Probleme zu beheben, wenn der Client die Analysen tatsächlich erhalten soll?

Ich weiß, es gibt viele Fragen hier, aber ich würde wirklich jede Hilfe zu schätzen wissen. Vielen Dank!

Antwort

17

Ich denke, die meisten Ihrer Bedenken sind unnötig. Nehmen Sie eine Ihrer Fragen nach der anderen:

1) Das größte Problem sind die benutzerdefinierten Attribute, unterschiedlich für jedes Ereignis. Dazu müssen Sie EAV (entity-attribute-value) Design verwenden. Die wichtige Frage ist: Welche Arten können diese Attribute haben? Wenn mehr als eins - z.B. String und Integer, dann ist es komplizierter. Es gibt im Allgemeinen zwei Arten solcher Entwurf:

  • Verwendung einer Tabelle und eine Spalte für Werte aller Art - und wandeln alles String (nicht skalierbare Lösung)

  • haben getrennte Tabellen für alle Daten Typ (sehr skalierbar, würde ich dafür gehen)

So würde sehen die Tabellen wie:

Events    EventId int, EventTypeId varchar, TS timestamp 
EventAttrValueInt EventId int, AttrName varchar, Value int 
EventAttrValueChar EventId int, AttrName varchar, Value varchar 

2) Was meinen Sie mit Segmentierung? Abfrage verschiedener Parameter des Ereignisses? In der EAV Design oben erwähnt, können Sie dies tun:

select * 
from Events 
    join EventAttrValueInt on Id = EventId and AttrName = 'APPVERSION' and Value > 4 
    join EventAttrValueChar on Id = EventId and AttrName = 'APP_NAME' 
              and Value like "%Office%" 
where EventTypeId = "APP_LAUNCH" 

Dadurch werden alle Ereignisse von APP_LAUNCH Typ auswählen, in dem appVersion> 4 und APP_NAME enthält "Office".

3) Eventtype Tabelle den Zweck der Konsistenz dienen könnte, das heißt, Sie könnten:

table EVENTS (.... EVENTTYPE_ID varchar - foreign key to EVENTTYPE ...) 
table EVENTTYPE (EVENTTYPE_ID varchar) 

Oder Sie ID als Zahl und haben Ereignisnamen in Eventtype Tabelle verwenden könnte - das spart Platz und ermöglicht die einfache Umbenennung der Ereignisse, aber Sie müssen diese Tabelle in jeder Abfrage beitreten (was zu etwas langsameren Abfragen führt). Hängt von der Priorität ab, Speicherplatz zu sparen, und von der geringeren Abfragezeit/Einfachheit.

4) Zeitstempel reichten Anfragen in Ihrem Design ist eigentlich sehr einfach sind:

select * 
from EVENTS 
where EVENTTYPE_ID = "APP_LAUNCH" and TIMESTAMP > '2013-11-1' 

5)"Ist es schlimm, eine Zeile für jedes Ereignis einfügen?"

Das hängt total von Ihnen ab! Wenn Sie für jedes Ereignis den Zeitstempel und/oder andere Parameter benötigen, sollten Sie wahrscheinlich für jedes Ereignis eine Zeile haben. Wenn es eine große Menge an Ereignissen desselben Typs und derselben Parameter gibt, können Sie wahrscheinlich das tun, was die meisten Logging-Systeme tun: Aggregieren Sie die Ereignisse, die in einer Zeile vorkommen. Wenn Sie so ein Bauchgefühl haben, dann ist es wahrscheinlich ein Weg zu gehen.

6)„Ich habe nicht genug Erfahrung mit SQL zu wissen, wie diese Abfragen durchführen über möglicherweise Hunderttausende dieser Einträge“

Hunderte oder Tausende solcher Einträge werden ohne Probleme behandelt werden.Wenn Sie eine Million erreichen, müssen Sie viel mehr über die Effizienz nachdenken.

7)"Würde eine aggregierte Tabelle oder ein In-Memory-Cache helfen, Probleme zu beheben, wenn der Client die Analysen tatsächlich erhalten soll?"

Natürlich ist dies auch eine Lösung, wenn die Abfragen langsam werden und Sie schnell reagieren müssen. Aber dann müssen Sie einen Mechanismus einführen, um den Cache periodisch zu aktualisieren. Es ist viel komplizierter; Vielleicht ist es besser, die Ereignisse auf der Eingabe zu aggregieren, siehe 5).

+0

Dies ist eine fantastische Antwort, aber ich habe eine Frage. Ich bin ein wenig unklar in Bezug auf Ihren Punkt in # 3. Wenn die EVENTTYPE_ID (Name des Ereignisses) bereits in der EVENTS-Tabelle vorhanden ist, wie entsteht Konsistenz durch einen Fremdschlüssel zu einer EVENTTYPE-Tabelle? – CCSab

+0

@CCSab, da Sie mithilfe des Fremdschlüssels die Konsistenzprüfung der internen Datenbank erzwingen können - dass nur diejenigen EVENTTYPE_IDs eingegeben werden können, die sich in der Tabelle EVENTTYPE befinden! Siehe [Fremdschlüsseleinschränkungen im Handbuch] (http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html) – TMS

+0

Oh, das macht eine Menge Sinn! Danke für die fantastische Antwort! Ich habe es akzeptiert und die Prämie ausgezeichnet :) – CCSab

Verwandte Themen