Jef*_*eff 5 logging database-design
我正在创建一些用于存储日志条目的数据库表.在正常情况下,我总是会规范化并且永远不会把价值放在一起,但我并不是100%确信这是一个好主意.
我可以正常化并拥有:
LogEntry与LogCategory具有多对多关系,LogEntry与LogEntryProperty(名称/值对)具有1对多的关系.
Alternative是一个非规范化版本,它只有LogEntry,类别存储为逗号分隔的字符串类别列表,属性存储为Name:Value格式化属性的逗号限制列表.听起来很丑陋,从报告,性能和可搜索性的角度来看,我不确定这是不是更好.
哪个更好?
谢谢.
因为只有几个不同的属性,所以我会远离名称 - 值对,并为每个属性提供一个具有正确名称和数据类型的单独表.我使用泛型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(尚未)上工作.
每次添加属性时,都必须添加新表并修改视图.