Det følgende er, hvordan jeg ville gøre det. Jeg har nogle flere kommentarer nederst, efter du har set skemaet.
Log
LogID - unikt log-id
Tid - dato/tidspunkt for begivenheden
LogType - String eller ID
(sidekommentar, jeg ville gå med et id her, så du kan bruge en meddelelsestabel vist nedenfor, men hvis du vil have hurtig og snavset, kan du bare bare en unik streng for hver logtid (f.eks. "Game Started", "Message Sendt" osv.)
LogActor
LogID - ekstern nøgle
LogActorType - Streng eller ID (som ovenfor, hvis ID skal du bruge en opslagstabel)
LogActorID - Dette er et unikt id til tabellen for typen f.eks. Bruger, Gruppe, Spil
Sekvens - dette er en bestilling af skuespillerne.
LogMessage
LogType - ekstern nøgle
Besked - lang streng (varchar(max)?)
Sprog - streng(5), så du kan slå et andet sprog fra, f.eks. "US-en"
Eksempeldata (ved hjælp af dine 3 eksempler)
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})
Bruger
ID Name
1 User A
2 User B
3 User C
Spil
ID Name
1 Name of game
Gruppe
ID Name
1 Name of group
Så her er de fine ting ved dette design.
-
Det er meget nemt at forlænge
-
Det håndterer flersprogede spørgsmål uafhængigt af aktørerne
-
Det er selvdokumenterende, LogMessage-tabellen forklarer nøjagtigt, hvad de data, du gemmer, skal sige.
Nogle dårlige ting ved det.
-
Du skal lave noget kompliceret behandling for at læse beskederne.
-
Du kan ikke bare se på DB og se, hvad der er sket.
Efter min erfaring opvejer de gode dele af denne form for design de dårlige ting. Hvad jeg har gjort for at give mig et hurtigt og beskidt kig på loggen, er at lave en visning (som jeg ikke bruger til applikationskoden), som jeg kan se på, når jeg skal se, hvad der foregår via bagsiden ende.
Sig til, hvis du har spørgsmål.
Opdatering – Nogle eksempler på forespørgsler
Alle mine eksempler er i sqlserver 2005+, lad mig vide, hvis der er en anden version, du vil have mig til at målrette mod.
Se LogActor-tabellen (Der er en række måder at gøre dette på, den bedste afhænger af mange ting, herunder datadistribution, use cases osv.) Her er to:
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
Generelt tror jeg, at a) er bedre end b) Hvis du for eksempel mangler en skuespiller, vil type a) inkludere den (med et nulnavn). Men b) er lettere at vedligeholde (fordi UNION ALL-sætningerne gør det mere modulært.) Der er andre måder at gøre dette på (f.eks. CTE, visninger osv.). Jeg er tilbøjelig til at gøre det som b), og ud fra hvad jeg har set ser det ud til at være i det mindste standard praksis, hvis ikke bedste praksis.
Så de sidste 10 elementer i loggen ville se sådan ud:
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
NB - Som du kan se, er det nemmere at vælge alle log-elementer fra en dato end sidste X, fordi vi skal bruge en (sikkert meget hurtig) underforespørgsel til dette.