我想在关系数据库中存储大量数据(在我的案例中,在RDS上使用postgresql),但我不确定要使用哪种结构。我遵循了包括数据库规范化的数据库课程,但我仍然不确定如何构建数据库。
我的数据包括气候模型的表格结果,按区域(水池)汇总。
[temperature,precipitation .. etc.]
长度= 11的参数
[1960 : 2014]
年
[1:12]
中的月份
区(盆地)[1 : 16000]
我的第一个选择是为每个指标创建一个单独的表,并按如下方式存储数据:
| ID | basin_id | temperature | unit | year | month | temporal_resolution |
|-------|----------|-------------|------|------|-------|---------------------|
| 1 | 1 | 42.1 | k | 2000 | 1 | month |
| 2 | 2 | 1.87 | k | 2000 | 1 | month |
| .. | .. | .. | .. | .. | .. | .. |
| 11001 | 1 | 40.3 | m3 | 2000 | 2 | month |
| 11002 | 2 | 2.3 | m3 | 2000 | 2 | month |
,第二个选项创建一个垂直表:
| ID | basin_id | indicator | value | unit | year | month | temporal_resolution |
|-------|----------|-------------|-------|------|------|-------|---------------------|
| 1 | 1 | temperature | 42.1 | k | 2000 | 1 | month |
| 2 | 2 | temperature | 1.87 | k | 2000 | 1 | month |
| .. | .. | .. | .. | .. | .. | .. | .. |
| 11001 | 1 | precipitation | 40.3 | m3 | 2000 | 2 | month |
| 11002 | 2 | precipitation | 2.3 | m3 | 2000 | 2 | month |
我的问题是建议还是不应该使用拆分指标名称和值。如果数据垂直存储,则总行数将为appr。 16000 * 11 * 12 * 55 = 116,160,000,我不确定是否易于管理。
| ID | basin_id | temperature_k | precipitation_m | … | riverdischarge_m3 | year | month | temporal_resolution |
|-------|----------|---------------|-----------------|----|-------------------|------|-------|---------------------|
| 1 | 1 | 42.1 | 42.1 | … | 42.1 | 2000 | 1 | month |
| 2 | 2 | 42.1 | 42.1 | | 42.1 | 2000 | 1 | month |
| .. | .. | .. | .. | .. | .. | .. | .. | .. |
| 11001 | 1 | 42.1 | 42.1 | .. | 42.1 | 2000 | 2 | month |
| 11002 | 2 | 42.1 | 42.1 | .. | 42.1 | 2000 | 2 | month |
这导致row_count为16000 * 55 * 12 = 10,560,000
答案 0 :(得分:2)
这似乎是在关系数据库中建模继承的一个示例。
你有一个抽象的实体 - "观察" - 使用属性zone
,year
和month
,具体实体" temperature_observation"用温度"属性,"降水"实体用"立方米"。
这个SO question概述了可用的选项 - 它们都不是特别干净。您的选项1是"每个子类的表"。
您的选项2不是常见的解决方案之一;它可供您使用,因为您的数据显然只有2个属性 - 数量(数字)和计量单位。这不是常见的情况。
选项3是"单表继承"。它是一种常见的设计模式,如果您的子类数量有限,通常可以使用;一旦你获得了很多子类,它就变得相当难以理解。
您需要考虑的下一件事是如何查询此数据。这是一个问题"返回给定时期/盆地的所有记录"?在这种情况下,它并不重要 - 你的选择都很好。
如果要将数据库用于更复杂的查询 -
哪个月的气温最高,降水量最低?
降水所在的盆地的平均温度是多少 至少x?
在我看来,选项1非常清楚 - 任何查看数据库查询的人都会一目了然地了解您所要求的内容。您将加入定义问题域的事物 - 盆地,年,月。
选项2和3需要自连接,随着条件变得更加复杂,这可能会变得相当复杂和难以阅读。
例如,选项1中的问题what's the average temperature in basins where precipitation is at least x?
是:
select avg(temperature)
from temperature_facts
where basin_id in
(select basin_id
from precipitation_facts
where precipitation > ?)
在选项2中,这变为:
select avg(value)
from facttable
where indicator = 'temperature'
and basin_id in
(select basin_id
from fact_table
where value > ?
and indicator = 'precipitation')
在选项3中,它类似于
select avg(temperature)
from fact_table
where basin_id in
(select basin_id
from fact_table
where precipitation > ?)
就个人而言,我发现选项1更具表现力,但这是一个偏好问题。
答案 1 :(得分:1)
由于我们也进行海洋研究,我了解您的需求(也许这是来自CTD的数据)。根据我的经验:
OTOH有些情况下,模型需要太多相同类型的数据,我观察到使用非传统方式来存储 事实证明数据要快得多。即:在一个日期范围内(比如说最后5个 年),某个参数是用固定的a期来衡量的 第二。这是每天86400个参数的测量值。 将它乘以5年,你最终会得到接近158的东西 百万价值,仅适用于某个地点。如果你需要存储 对于20个地点,那么你需要超过30亿行的数据 你以传统方式做到这一点。如果它也不影响存储, 我想说这是ETL的问题和之后的分析。 如果你这样做,采用传统方法:
LocationID(int),Datetime(每秒递增),Value
它看起来很无辜但只是存储量超过30 Gb。所以我采取了另一种方法并存储:LocationId,date(not datetime),oneDayWorthValues(作为二进制,每秒固定,如果值范围适合2个字节,那么每行恰好有86400 * 2个字节的二进制数据) - 我使用的数据库没有数组数据类型。
只需我0.05美分,但如果您也可以做类似的事情(水资源数据很少),也许值得。