具有有限域的文本字段:是否考虑子表?

时间:2014-11-25 15:39:58

标签: postgresql database-design database-normalization

新数据库用于存储(系列)Web服务器的日志数据。日志记录的结​​构已转换为这种“天真”的通用模式:

CREATE TABLE log (
    matchcode SERIAL PRIMARY KEY,
    stamp TIMESTAMP WITH TIME ZONE,
    ip INET,
    bytes NUMERIC,
    vhost TEXT,
    path TEXT,
    user_agent TEXT,
    -- and so on
);

依此类推,还有更多的领域,但这显示了一般原则。大部分数据包含在自由文本字段中,如上所示。当然,从长远来看,这将使数据库变得相当大。我们正在谈论一个Web服务器日志,所以这并不是一个大惊喜。

但是,这些文本字段的域名是有限的。例如有一组非常有限的虚拟主机,可以看到,一个更大,但仍然是有限的路径,用户代理等等。在这种情况下,将文本字段分解为子表更合适,并仅通过标识符引用它们吗?我正在考虑这样一条线:

CREATE TABLE vhost ( ident SERIAL PRIMARY KEY, vhost TEXT NOT NULL UNIQUE );
CREATE TABLE path ( ident SERIAL PRIMARY KEY, path TEXT NOT NULL UNIQUE );
CREATE TABLE user_agent ( ident SERIAL PRIMARY KEY, user_agent TEXT NOT NULL UNIQUE );

CREATE TABLE log (
    matchcode SERIAL PRIMARY KEY,
    stamp TIMESTAMP WITH TIME ZONE,
    ip INET,
    bytes NUMERIC,
    vhost INTEGER REFERENCES vhost ( ident ) ,
    path INTEGER REFERENCES path ( ident ),
    user_agent INTEGER REFERENCES user_agent ( ident ),
    -- and so on
);

我现在尝试了两种方法。正如预期的那样,第二个通过给出或取三因子来小得多。但是,由于涉及所有连接,查询会变得非常慢。差异大约是一个数量级。

据我了解,在这两种情况下,表格应该足够正常。在项目的某个稍后阶段,可能会有其他属性附加到各种文本值(如有关每个vhost的其他信息等)。

实际考虑是显而易见的,它基本上是一个空间/时间权衡。从长远来看,在这种情况下,最佳做法是什么?对于我可能想要了解的这种情况,还有其他的,或许更具理论意义吗?

1 个答案:

答案 0 :(得分:1)

  

但是,这些文本字段的域名是有限的。例如有一个   非常有限的一组vhosts将被看到,更大,但仍然   绝对有限的路径集,用户代理等等。在喜欢的情况下   这样,将文本字段考虑在内是否更合适   子表,并仅通过标识符引用它们?

有几种不同的方法可以看待这类问题。无论你采用哪种方式,适当的都是一个模糊的词。

<强>约束

让我们设想你创建一个表和一个外键约束来允许&#34; vhost&#34;列只接受五个值。您是否还可以将Web服务器限制为将这五个值写入日志文件?不,你不能。

可以添加一些代码以将新虚拟主机插入到引用的表中。您甚至可以使用触发器自动执行此操作。但是当你这样做时,你不再约束&#34; vhost&#34;的值。无论您使用自然键还是代理键,这都是正确的。

带有ID号的数据压缩

您还可以将此视为数据压缩问题。通过将整数用作唯一文本表的外键,可以节省空间 - 可能是空间的批次。您可能节省时间。需要大量连接的查询通常比只直接读取数据的查询要慢。你已经看过了。


在你的情况下,这与机器生成的日志文件有关,我更喜欢将它们存储起来,因为它们来自设备(网络服务器,流量传感器,无论如何),除非有令人信服的理由不这样做。

在少数情况下,我曾在域专家确定某些类型的值不应从日志文件传输到数据库的系统上工作过。例如,领域专家可能会认为传感器的负数意味着传感器坏了。使用CHECK()约束可以更好地处理这种约束,但原理是相同的。

获取设备为您提供的内容,除非有令人信服的理由不这样做。