2013-09-23 9 views
11

Próbuję znaleźć najlepszy sposób modelowania schematu dla tego opartego na zdarzeniach systemu analitycznego, który piszę. Moim głównym zmartwieniem jest pisanie tego w sposób, który sprawia, że ​​zapytania są proste i szybkie. Będę również używać MySQL. Przeanalizuję niektóre wymagania i przedstawię zarys możliwego (ale moim zdaniem kiepskiego) schematu.Projektowanie schematu bazy danych do analiz opartych na zdarzeniach

Wymagania

  • Konkurencje biegowe (np zdarzeń ścieżki "APP_LAUNCH" Event)

  • Definiowanie niestandardowych zdarzeń

  • zdolność do wydarzeń segment na> 1 właściwości niestandardowych (np get wystąpienia "APP_LAUNCH" podzielone na segmenty "APP_VERSION")

  • Sesje śledzące

  • Wykonywanie zapytań na podstawie zakresu datownika

Możliwe Modeling

Głównym problemem, który mam jest jak model segmentacji i zapytań wykonać, aby uzyskać ogólne liczniki zdarzenia .

Mój oryginalny pomysł polegał na zdefiniowaniu tabeli WYDARZENIA z identyfikatorem, liczbą int, datownikiem, właściwością (?) I kluczem obcym na EVENTTYPE. EVENTTYPE ma identyfikator, nazwę i dodatkowe informacje należące do typowego zdarzenia.

Na przykład zdarzenie "APP_LAUNCH" będzie miało wpis w tabeli WYDARZENIA z unikalnym identyfikatorem, liczba określająca, ile razy zdarzenie miało miejsce, znacznik czasu (nie ma pewności, co to jest podstemplowane) oraz właściwość lub lista właściwości (np. "APP_VERSION", "COUNTRY" itd.) i klucz obcy na EVENTTYPE o nazwie "APP_LAUNCH".

Uwagi i pytania

Jestem całkiem pewien, że to nie jest dobry sposób, aby modelować to z następujących powodów. Utrudnia to wykonywanie zapytań z datownikiem ("Liczba APP_LAUNCHES między czasem xiy"). Tabela EVENTTYPE tak naprawdę nie służy żadnemu celowi. Na koniec nie jestem pewien, w jaki sposób mogę wykonywać kwerendy dla różnych segmentacji. Ten ostatni najbardziej mnie martwi.

Byłbym wdzięczny za pomoc w poprawnym modelowaniu tego lub wskazaniu mi zasobów, które mogłyby pomóc.

Ostatnie pytanie (które prawdopodobnie jest głupie): Czy wstawianie wiersza do każdego wydarzenia jest złe? Na przykład, powiedzmy, moja biblioteka stronie klienta sprawia następujące wezwanie do mojego API:

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

Jak bym to właściwie przechowywać w tabeli (to jest ściśle związane z projektowaniem schematu oczywiście)? Czy źle jest po prostu wstawić wiersz dla każdego z tych połączeń, z których może być znaczna kwota? Moją reakcją jest to, że jestem naprawdę zainteresowany głównie ogólnymi zbiorowymi danymi. Nie mam wystarczającego doświadczenia z SQL, aby wiedzieć, jak te zapytania wykonują ponad setki tysięcy takich wpisów. Czy zagregowana tabela lub pamięć podręczna w pamięci pomogłyby w złagodzeniu problemów, gdy chcę, aby klient rzeczywiście pobierał dane analityczne?

Zdaję sobie sprawę, że jest tu wiele pytań, ale byłbym wdzięczny za wszelką pomoc. Dzięki!

Odpowiedz

17

Myślę, że większość twoich obaw jest niepotrzebna. Kolejne pytanie:

1) Największym problemem są atrybuty niestandardowe, różne dla każdego zdarzenia. W tym celu należy użyć projektu EAV (entity-attribute-value). Ważne pytanie brzmi: jakie typy mogą mieć te atrybuty? Jeśli więcej niż jeden - np. ciąg i liczba całkowita, to jest bardziej skomplikowane. Są to na ogół dwa rodzaje takiej konstrukcji:

  • użyć jednej tabeli i jednej kolumny dla wartości wszelkiego rodzaju - i konwertować wszystko na ciąg (nie skalowalne rozwiązanie)

  • mają oddzielne tabele dla każdej danych typ (bardzo skalowalne, pójdę do tego)

Tak, stoły wyglądałby następująco:

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

2) Co masz na myśli przez segmentację? Zapytanie o różne parametry wydarzenia? W projekcie EAV wspomniano powyżej, można to zrobić:

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" 

To będzie wybrać wszystkie zdarzenia typu APP_LAUNCH gdzie APPVERSION wynosi> 4 i APP_NAME zawiera „Office”.

3) tabela EventType mogłyby służyć spójności, czyli możesz:

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

Albo można użyć identyfikatora jako liczby i mieć nazwę zdarzenia w tabeli EventType - to oszczędność miejsca i pozwala na łatwe zmienianie nazw zdarzeń, ale będziesz musiał dołączyć do tej tabeli w każdym zapytaniu (co spowoduje nieco wolniejsze zapytania). Zależy od priorytetu oszczędzania przestrzeni dyskowej w porównaniu z niższym czasem/prostotą zapytania.

4) datownik wahała zapytania są rzeczywiście bardzo prosty w swojej konstrukcji:

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

5)"Czy to źle, aby wstawić wiersz dla każdego zdarzenia?"

To całkowicie zależy od Ciebie! Jeśli potrzebujesz sygnatury czasowej i/lub innych parametrów każdego takiego zdarzenia, prawdopodobnie powinieneś mieć rząd dla każdego zdarzenia. Jeśli istnieje ogromna liczba zdarzeń tego samego rodzaju i parametrów, prawdopodobnie możesz zrobić to, co robi większość systemów logujących: agreguj zdarzenia, które występują w jednym wierszu. Jeśli masz takie przeczucie, to prawdopodobnie jest to droga.

6)„nie mam wystarczająco dużo doświadczenia z SQL, aby wiedzieć, jak te zapytania wykonać ponad ewentualnie setki tysięcy tych wpisów”

setki lub tysiące takie wpisy będą obsługiwane bez problemów.Kiedy osiągniesz milion, będziesz musiał myśleć o wiele więcej na temat wydajności.

7)„Czy agregat stół lub w pamięci cache pomaga złagodzić problemy, gdy chcę klient rzeczywiście dostać Analytics?”

Oczywiście jest to również rozwiązanie, jeśli zapytania stają się powolne i trzeba szybko reagować. Ale musisz wprowadzić pewien mechanizm okresowego odświeżania pamięci podręcznej. To jest zbyt skomplikowane; może lepiej rozważyć agregację zdarzeń na wejściu, patrz 5).

+0

To jest fantastyczna odpowiedź, ale mam pytanie. Jestem trochę niejasny co do twojego punktu w # 3. Jeśli EVENTTYPE_ID (nazwa zdarzenia) już istnieje w tabeli EVENTS, w jaki sposób powstaje konsekwencja posiadania obcego klucza do tabeli EVENTTYPE? – CCSab

+0

@CCSab, ponieważ za pomocą klucza obcego można wymusić sprawdzanie spójności wewnętrznej bazy danych - można wprowadzić tylko te EVENTTYPE_ID, które znajdują się w tabeli EVENTTYPE! Zobacz [ograniczenia klucza obcego w podręczniku] (http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html) – TMS

+0

To sprawia, że ​​masz dużo sensu! Dzięki za fantastyczną odpowiedź! Zaakceptowałem to i nagrodzono nagrodą :) – CCSab

Powiązane problemy