我有时间戳记的地理位置数据和有关用户的其他一些信息,我正在寻找有关设计数据库的建议。我想天真的设计是:
CREATE TABLE user(
user_id INT NOT NULL,
name VARCHAR(128) NOT NULL,
gender VARCHAR(128) NOT NULL,
age INT NOT NULL,
time TIMESTAMPTZ NOT NULL,
xloc FLOAT(4) NOT NULL,
yloc FLOAT(4) NOT NULL,
PRIMARY KEY(user_id),
);
此处xloc, yloc
是表示位置的浮点数。该表的明显问题是,对于每个时间戳,字段gender
,age
和name
将被重复多次重复。在阅读Storing time-series data, relational or non?中非常全面的接受的答案之后,我决定一个更好的解决方案是将地理位置数据存储在单独的表中,即具有两个表:
CREATE TABLE geodata(
user_id INT NOT NULL,
time TIMESTAMPTZ NOT NULL,
xloc FLOAT(4) NOT NULL,
yloc FLOAT(4) NOT NULL,
PRIMARY KEY (user_id, time),
);
CREATE TABLE user(
user_id INT NOT NULL,
name VARCHAR(128) NOT NULL,
gender VARCHAR(128) NOT NULL,
age INT NOT NULL,
PRIMARY KEY (user_id),
);
请注意,在geodata
表中,我同时使用user_id
和time
作为PK来尝试符合第六范式(6NF)上述链接中的答案所建议-大概可以提高性能。严格来说,6NF requires only one other attribute for each PK
,但就我而言,我有两个(xloc
和yloc
)。最新的PostgreSQL版本允许使用array types,因此另一种选择是:
CREATE TABLE geodata(
user_id INT NOT NULL,
time TIMESTAMPTZ NOT NULL,
loc FLOAT(4) ARRAY[2] NOT NULL,
PRIMARY KEY (user_id, time),
);
在这种情况下,客户端应该知道该数组以该顺序表示x
和y
的位置,但是现在这不是问题。从技术上讲,该表现在每个PK仅具有一个属性,但是我对其性能更感兴趣。我是Postgres和DB的新手。就性能而言,使用数组类型会更好吗?
数据和用例:每个用户的位置时间序列可能长达数千万次测量,并且间隔不同。 read 操作将超过 write 操作-实际上,现在我的数据是静态的,并且至少到现在为止,小型团队将使用所得数据库进行统计分析。 我的查询将是男性用户的测量值,或30岁以下用户的星期天测量值。
您会推荐哪些替代设计?
答案 0 :(得分:1)
时间序列和时间数据本身不使用6NF。 (在该链接上定位。)需要的是您要记录原子更改的CK和相关数据。只是经常需要6NF,但这本身并不是目标。非CK数据可以是多列-您要记录对位置而不是对坐标的更改。 (类似地,当您想知道整数是否发生变化时,没有人为您没有每个CK和数字提供一个表。)您可以将其视为具有CK和一个元组或记录的6NF表的转换。值列。
因此,这里有CK&X&Y的设计很好-只要您不需要知道何时更改特定坐标值即可。
“我一般对Postgres和DB还是陌生的。”然后忘掉“性能”,直到您学到足够的知识来了解它的含义。进行简单的设计。接下来了解约束和索引。
关于时间数据(包括6NF),每个人都应阅读Date,Darwen和Lorentzos。避免吃草皮草。
PS PK与关系模型理论无关,CK很重要,而PK只是您称为PK的某些CK。 PS请注意,SQL PK或多或少是超键而不是CK;它可以包含一个较小的UNIQUE /超级键。
PS 6NF表示不满足非平凡的JD。它暗示“主键,最多还有一个其他属性”,但后者不是6NF的定义。还要注意,这种情况本身并不意味着一个CK。可能还会更多。
PS维基百科不是用于关系模型信息的声音源。例如There's no one "1NF",它们与归一化为6NF的NF正交。例如PK没关系。例如,不能通过移动较低的NF来完成对较高NF的标准化。 (此外,它可能排除良好的目标NF设计。)例如,在导致6NF的NF中,DKNF不属于该页面。例如,它对6NF的定义是错误的。