数据库日志表结构

Jef*_*eff 5 logging database-design

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

我可以正常化并拥有:

  • LogEntry
  • LogEntryCategory
  • LogCategory
  • LogEntryProperty

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

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

哪个更好?

谢谢.

Dam*_*vic 7

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

在此输入图像描述

这里的事情是确保在缺少属性表时不插入值,换句话说,所有属性值都是NOT 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
Run Code Online (Sandbox Code Playgroud)

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

select
      LogCategoryName
    , LogTime
    , p1_Value
    , p2_Value
from dbo.vLogs
where LogCategoryName = 'some_category' 
  and LogTime between from_time and to_time
Run Code Online (Sandbox Code Playgroud)

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

select max(p1_Value)
from dbo.vLogs
where LogTime between '2011-07-18' and '2011-07-19'
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

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