数据库日志表结构

时间:2011-07-19 18:09:04

标签: database-design logging

我正在创建一些用于存储日志条目的数据库表。在正常情况下,我总是会规范化并且永远不会把价值放在一起,但我并不是100%确信这是一个好主意。

我可以正常化并拥有:

  • LogEntry
  • LogEntryCategory
  • LogCategory
  • LogEntryProperty

LogEntry与LogCategory有多对多的关系,LogEntry与LogEntryProperty(名称/值对)有1对多的关系。

Alternative是一个非规范化版本,它只有LogEntry,类别存储为逗号分隔的字符串类别列表,属性存储为Name:Value格式化属性的逗号限制列表。听起来很丑陋,从报告,性能和可搜索性的角度来看,我不确定这是不是更好。

哪个更好?

感谢。

2 个答案:

答案 0 :(得分:6)

因为只有几个不同的属性,所以我会远离名称 - 值对,并为每个属性提供一个单独的表,其中包含正确的名称和数据类型 。我使用了通用Property_,仅用于演示。

enter image description here

这里的事情是确保在缺少属性表时不将值插入属性表中,换句话说,所有属性值都不是NULL。

为了让生活更轻松,请定义视图

create view dbo.vLogs AS
select
      LogCategoryName
    , LogTime
    , p1_Value
    , p2_Value
    , p3_Value
    , p4_Value
    , p5_Value  
from LogEntry              as e
left join Property_1       as p1 on p1.LogEntryId   = e.LogEntryId
left join Property_2       as p2 on p2.LogEntryId   = e.LogEntryId
left join Property_3       as p3 on p3.LogEntryId   = e.LogEntryId
left join Property_4       as p4 on p4.LogEntryId   = e.LogEntryId
left join Property_5       as p5 on p5.LogEntryId   = e.LogEntryId
left join LogEntryCategory as x  on x.LogEntryId    = e.LogEntryId
left join LogCategory      as c  on c.LogCategoryID = x.LogCategoryID

这个观点(查询)看起来复杂而漫长;但是,如果您尝试下面的查询并查看执行计划,您可能会注意到选择列表中未提及的属性表未包含在计划中(未触及)。

select
      LogCategoryName
    , LogTime
    , p1_Value
    , p2_Value
from dbo.vLogs
where LogCategoryName = 'some_category' 
  and LogTime between from_time and to_time

如果你需要像这样简单的东西

select max(p1_Value)
from dbo.vLogs
where LogTime between '2011-07-18' and '2011-07-19'

这是执行计划,因为您只能看到涉及两个表。

enter image description here

这称为表(连接)消除,你需要SQL Server,Oracle,PostgreSql 9.x,...为此工作 - 将无法在MySql(尚未)上工作。

每次添加属性时,都必须添加新表并修改视图。

答案 1 :(得分:1)

我建议正确规范化。