Udělal bych to následovně. Poté, co jste viděli schéma, mám v dolní části několik dalších komentářů.
Protokol
LogID – jedinečné ID protokolu
Čas – datum/čas události
LogType – Řetězec nebo ID
(vedlejší komentář, zde bych šel s ID, takže můžete použít tabulku zpráv uvedenou níže, ale pokud chcete rychle n špinavé, můžete pouze jedinečný řetězec pro každý čas přihlášení (např. „Hra zahájena“, „Zpráva odeslána“ , atd.)
LogActor
LogID - externí klíč
LogActorType – řetězec nebo ID (jak je uvedeno výše, pokud ID budete potřebovat vyhledávací tabulku)
LogActorID – Toto je jedinečné ID tabulky pro typ např. User, Group, Game
Sekvence - to je pořadí herců.
Zpráva protokolu
LogType - externí klíč
Zpráva - dlouhý řetězec (varchar(max)?)
Language - string(5), takže můžete vyřadit jiný jazyk, např. "US-en"
Příklad dat (s použitím vašich 3 příkladů)
Log
ID Time LogType
1 1/1/10 1
2 1/1/10 2
3 1/1/10 3
LogActor
LogID LogActorType LogActorID Sequence
1 User 1 1
1 User 2 2
2 User 1 1
2 User 2 2
2 User 2 3
2 Game 1 4
3 User 3 1
3 Group 1 2
LogMessage
LogType Message
1 {0} Made a new friend {1}
2 {0}, {1}, {2} played a game ({3})
3 {0} joined a group ({1})
Uživatel
ID Name
1 User A
2 User B
3 User C
Hra
ID Name
1 Name of game
Skupina
ID Name
1 Name of group
Takže tady jsou hezké věci na tomto designu.
-
Je velmi snadné prodloužit
-
Řeší vícejazyčné problémy nezávisle na aktérech
-
Je to samodokumentující, tabulka LogMessage přesně vysvětluje, co by měla data, která ukládáte, říkat.
Některé špatné věci na tom.
-
Pro čtení zpráv musíte provést nějaké složité zpracování.
-
Nemůžete se jen podívat na DB a zjistit, co se stalo.
Podle mých zkušeností převažují dobré části tohoto druhu designu nad špatnými částmi. Co jsem udělal, abych se mohl rychle podívat na protokol, je vytvořit pohled (který nepoužívám pro kód aplikace), na který se mohu podívat, když potřebuji vidět, co se děje přes zadní stranu konec.
Pokud máte dotazy, dejte mi vědět.
Aktualizace – několik příkladů dotazů
Všechny mé příklady jsou v sqlserver 2005+, dejte mi vědět, pokud existuje jiná verze, na kterou chcete cílit.
Zobrazit tabulku LogActor (Existuje několik způsobů, jak to udělat, nejlepší závisí na mnoha věcech, včetně distribuce dat, případů použití atd.) Zde jsou dva:
a)
SELECT
LogId,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Sequence
FROM LogActor A
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
b)
SELECT
LogId,
U.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
UNION ALL
SELECT
LogId,
Ga.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
UNION ALL
SELECT
LogId,
Go.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
Obecně si myslím, že a) je lepší než b) Pokud vám například chybí herec, typ a) jej zahrne (s nulovým jménem). Nicméně b) se snadněji udržuje (protože příkazy UNION ALL jej dělají modulárnějším.) Existují i jiné způsoby, jak toho dosáhnout (např. CTE, pohledy atd.). Mám sklon dělat to jako b) a z toho, co jsem viděl, se to zdá být přinejmenším standardní, ne-li nejlepší praxe.
Posledních 10 položek v protokolu by tedy vypadalo nějak takto:
SELECT
LogId,
M.Message,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Time,
A.Sequence
FROM Log
LEFT JOIN LogActor A ON Log.LogID = A.LogID
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
LEFT JOIN LogMessage M ON Log.LogType = M.LogMessage
WHERE LogID IN (SELECT Top 10 LogID FROM Log ORDER BY Date DESC)
ORDER BY Date, LogID, A.Sequence
Pozn. – Jak vidíte, je jednodušší vybrat všechny položky protokolu od data než posledního X, protože k tomu potřebujeme (pravděpodobně velmi rychlý) dílčí dotaz.