sql >> Databáze >  >> RDS >> Mysql

Databáze:Tvorba protokolu akcí, jak zacházet s různými referencemi?

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.



  1. Hibernate:Při pokusu o získání zámku bylo zjištěno uváznutí

  2. Nelze načíst ID posledního vloženého řádku v režimu spánku pomocí Oracle

  3. pomocí implode pro pole uvnitř mysql kde v klauzuli

  4. Měl by MAMP vrátit ::1 jako IP na localhost?