以下是我将如何做到这一点.
看到架构后,我在底部会有更多评论.
日志
LogID – 唯一的日志ID
时间 – 事件的日期/时间
LogType – 字符串或ID
(侧面评论,我会在这里使用id,所以你可以使用下面显示的消息表,但如果你想快速n脏,你可以只为每个日志时间一个唯一的字符串(例如“游戏开始”,“消息已发送”)等)
LogActor
LogID – 外部密钥
LogActorType – 字符串或ID(如上所述,如果ID需要查找表)
LogActorID – 这是表格的唯一ID,例如User,Group,Game
序列 – 这是演员的排序.
的LogMessage
LogType – exernal键
消息 – 长字符串(varchar(max)?)
语言 – 字符串(5),因此您可以键入不同的语言,例如“US-en”
示例数据
(使用你的3个例子)
日志
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})
用户
ID Name
1 User A
2 User B
3 User C
游戏
ID Name
1 Name of game
组
ID Name
1 Name of group
所以这里有关于这个设计的好东西.
>它很容易扩展
>它处理多语言问题
独立于演员
>这是自我记录,
LogMessage表完全解释
您存储的数据应该是什么
说.
关于它的一些不好的事情.
>您必须执行一些复杂的处理才能阅读消息.
>你不能只看数据库,看看发生了什么.
根据我的经验,这种设计的好部分超过了坏点.我做了什么让我快速看看日志是一个视图(我不用于应用程序代码),当我需要通过后面看到发生了什么时,我可以看到结束.
如果您有疑问,请告诉我.
更新 – 一些示例查询
我的所有示例都在sqlserver 2005中,如果您希望我定位的是另一个版本,请告诉我.
查看LogActor表
(有很多方法可以做到这一点,最好的方法取决于许多事情,包括数据分发,用例等)
这是两个:
一个)
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
一般来说,我认为a)比b)更好.例如,如果你缺少一个actor类型a)将包含它(使用空名称).但是b)更容易维护(因为UNION ALL语句使其更加模块化.)还有其他方法可以做到这一点(例如CTE,视图等).我倾向于像b)那样做,从我所看到的,如果不是最佳实践,似乎至少是标准做法.
所以,日志中的最后10个项目看起来像这样:
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
注意 – 正如您所看到的,从日期中选择所有日志项比从最后一个X更容易,因为我们需要一个(可能非常快)的子查询.