构建 "sparse" 数据 table + ORM(+ NoSQL?)
Structuring a "sparse" data table + ORM ( + NoSQL?)
我正在开发一款热力学模拟软件(C++),我需要存储不同温度下的流体特性。这些数据点用于构建一个简单的插值函数,以便在我们没有完整实验数据的温度下评估属性值。
一种流体可以简单地通过其名称和浓度(%)来识别(后者通常是无关紧要的)。如果你很好奇,有四个属性值得关注:质量密度、动态粘度、比热容 和 热导率 。对于任何其他意图和目的,这些只是 4 个数字属性,称它们为 A、B、C 和 D。
所以特定流体的函数看起来像这样:(A,B,C,D) = f(T)
,其中 T 是温度。
目前,它是一个 SQLite3 数据库,table 的流体看起来像这样:
+----+-------+---------------+
| id | name | concentration |
+====+=======+===============+
| 1 | Water | 100 |
+----+-------+---------------+
| 2 | ..... | ... |
还有属性table:
+----------+-------------+---------+-----------+--------------+----------+
| fluid_id | temperature | density | viscosity | conductivity | capacity |
+==========+=============+=========+===========+==============+==========+
| 2 | 373.15 | 1045.48 | 0.412 | 1.415 | 0.845 |
| 3 | 273.15 | 1105.0 | 2.113 | 0.4688 | 0.849 |
| 3 | 283.15 | | 1.678 | 0.4859 | 0.8503 |
| 3 | 293.15 | 1098.0 | 1.353 | 0.5015 | 0.5833 |
| 3 | 303.15 | | 1.08 | 0.5164 | |
| 3 | 313.15 | 1090.0 | 0.893 | 0.532 | 0.8561 |
| 3 | 323.15 | | 0.748 | 0.5432 | |
| 3 | 333.15 | 1080.0 | 0.644 | 0.5543 | 0.8577 |
| 3 | 343.15 | | 0.563 | 0.564 | |
| 3 | 353.15 | 1068.0 | 0.499 | 0.5722 | 0.8612 |
| 3 | 363.15 | | 0.44 | 0.5796 | |
| 3 | 373.15 | 1054.0 | 0.39 | 0.5856 | |
+----------+-------------+---------+-----------+--------------+----------+
手动插入数据进行测试没问题。这也将是以后流体编辑器 GUI 的直观显示。
然而,在代码中,插值是针对每个 属性 单独完成的。此外,由于我不能使用 NULL 值,因此并非所有温度(行)都与所有属性相关。为了使事情适应代码的观点,我创建了四个相同的 视图 - 每个 属性 一个。例如:
+----+-----------+---------------+-------------+-------+
| id | name | concentration | temperature | value |
+====+===========+===============+=============+=======+
| 2 | Sea Water | 22 | 373.15 | 0.412 |
| 3 | Sea Water | 14 | 273.15 | 2.113 |
| 3 | Sea Water | 14 | 283.15 | 1.678 |
| 3 | Sea Water | 14 | 293.15 | 1.353 |
| 3 | Sea Water | 14 | 303.15 | 1.08 |
| 3 | Sea Water | 14 | 313.15 | 0.893 |
| 3 | Sea Water | 14 | 323.15 | 0.748 |
| 3 | Sea Water | 14 | 333.15 | 0.644 |
| 3 | Sea Water | 14 | 343.15 | 0.563 |
| 3 | Sea Water | 14 | 353.15 | 0.499 |
| 3 | Sea Water | 14 | 363.15 | 0.44 |
| 3 | Sea Water | 14 | 373.15 | 0.39 |
+----+-----------+---------------+-------------+-------+
现在,当我逐渐从原型设计转向构建合适的软件时,我正在尝试思考这些方法中的任何一种如何适合 ORM 视角。它是每个 属性 的模型(如我的观点)还是所有属性的单个模型(如当前使用的 table)。
第三种选择可能是保留数据库原样并在视图之上构建模型(而不是真正的 tables),但这不是 ORM 的方式。
我什至考虑过将此数据集移动到 NoSQL 解决方案(例如 MongoDb),但我想不出克服双重视角问题的方法。
我承认这里既没有运行时也没有space性能问题,而且要存储和处理的数据量也可以忽略不计。一个小时内可能只有两个查询,每个查询都将特定流体的数据集加载到应用程序的内存中并在那里使用它(基于评估的插值和计算)。
所以如果你认为我对此压力过大,我会接受它。
否则,我想听听您的想法并考虑您可能提供的任何不同方法。我错过了什么吗?拆分 table 会产生的键冗余(流体和温度)怎么样?此外,其他设置了约束的人可能对此感兴趣。
每个带有 NULL 的 table 表示 "missing"("unknown" 或 "inapplicable")值对应于删除 NULLable 列并引入另一个 table 的架构使用原始的一些(超级)键并仅保留其中该列中不为 NULL 的行。
Null 支持更轻松的人类同时读取这些单独的相同(超级)密钥 table。但是它们使其他一切变得复杂,包括 meaning of a table(行进入或停留的 criterion/predicate),因此基础设计和查询组合。通常我们会尽快删除所有未粘贴到键以在最终输出中显示的 NULL。 (例如,OUTER JOIN 通常习惯上用于引入然后删除 NULL 以表达无 NULL EXCEPT/MINUS。)我们使用单独的 tables 的含义来表达 table 的含义NULL 和使用它的查询的含义。我们从组合的 NULL 视图中提取单独的 tables 以进行基本上任何处理。
直接的关系解决方案是单独的 tables。 SQL 传统是为一个 table。其他 SQL 理由是减少了合并 table 的 JOIN。但这仅适用于最终的人类可读输出!要处理那个 table,您无论如何都必须提取单独的视图。
PS
回复 "the redundancy of keys (fluid and temperature) that splitting the table would incur":相同(子行)值在列、table 或数据库中出现多次,不存在“redundancy”。当两个基础 table 或行做出相同的断言时,就会出现冗余。代入 criterion/predicate 的行给出 statement/proposition;当前行断言它的,不存在的行断言不是它的; table(命题)断言其存在行和不存在行的断言的合取。 (并且数据库(命题)断言其 table 的命题的合取。)此外,冗余不一定是坏事;在时间、space 和复杂性之间总是存在工程权衡。
PPS
ORM 有视图:延迟或惰性查询评估。由于您稍后可以在另一个查询中使用这样的查询,因此它就像一个视图一样。它是 ORM 查询语言而非 DBMS 查询语言中查询的命名表示。可以想象这可以用于更新命令(如果可能)以及查询。这取决于 DBMS/ORM。然而,视图更新基本上是一种方便,因为它总是可以用成分 tables.
的更新来表示
我正在开发一款热力学模拟软件(C++),我需要存储不同温度下的流体特性。这些数据点用于构建一个简单的插值函数,以便在我们没有完整实验数据的温度下评估属性值。
一种流体可以简单地通过其名称和浓度(%)来识别(后者通常是无关紧要的)。如果你很好奇,有四个属性值得关注:质量密度、动态粘度、比热容 和 热导率 。对于任何其他意图和目的,这些只是 4 个数字属性,称它们为 A、B、C 和 D。
所以特定流体的函数看起来像这样:(A,B,C,D) = f(T)
,其中 T 是温度。
目前,它是一个 SQLite3 数据库,table 的流体看起来像这样:
+----+-------+---------------+
| id | name | concentration |
+====+=======+===============+
| 1 | Water | 100 |
+----+-------+---------------+
| 2 | ..... | ... |
还有属性table:
+----------+-------------+---------+-----------+--------------+----------+
| fluid_id | temperature | density | viscosity | conductivity | capacity |
+==========+=============+=========+===========+==============+==========+
| 2 | 373.15 | 1045.48 | 0.412 | 1.415 | 0.845 |
| 3 | 273.15 | 1105.0 | 2.113 | 0.4688 | 0.849 |
| 3 | 283.15 | | 1.678 | 0.4859 | 0.8503 |
| 3 | 293.15 | 1098.0 | 1.353 | 0.5015 | 0.5833 |
| 3 | 303.15 | | 1.08 | 0.5164 | |
| 3 | 313.15 | 1090.0 | 0.893 | 0.532 | 0.8561 |
| 3 | 323.15 | | 0.748 | 0.5432 | |
| 3 | 333.15 | 1080.0 | 0.644 | 0.5543 | 0.8577 |
| 3 | 343.15 | | 0.563 | 0.564 | |
| 3 | 353.15 | 1068.0 | 0.499 | 0.5722 | 0.8612 |
| 3 | 363.15 | | 0.44 | 0.5796 | |
| 3 | 373.15 | 1054.0 | 0.39 | 0.5856 | |
+----------+-------------+---------+-----------+--------------+----------+
手动插入数据进行测试没问题。这也将是以后流体编辑器 GUI 的直观显示。
然而,在代码中,插值是针对每个 属性 单独完成的。此外,由于我不能使用 NULL 值,因此并非所有温度(行)都与所有属性相关。为了使事情适应代码的观点,我创建了四个相同的 视图 - 每个 属性 一个。例如:
+----+-----------+---------------+-------------+-------+
| id | name | concentration | temperature | value |
+====+===========+===============+=============+=======+
| 2 | Sea Water | 22 | 373.15 | 0.412 |
| 3 | Sea Water | 14 | 273.15 | 2.113 |
| 3 | Sea Water | 14 | 283.15 | 1.678 |
| 3 | Sea Water | 14 | 293.15 | 1.353 |
| 3 | Sea Water | 14 | 303.15 | 1.08 |
| 3 | Sea Water | 14 | 313.15 | 0.893 |
| 3 | Sea Water | 14 | 323.15 | 0.748 |
| 3 | Sea Water | 14 | 333.15 | 0.644 |
| 3 | Sea Water | 14 | 343.15 | 0.563 |
| 3 | Sea Water | 14 | 353.15 | 0.499 |
| 3 | Sea Water | 14 | 363.15 | 0.44 |
| 3 | Sea Water | 14 | 373.15 | 0.39 |
+----+-----------+---------------+-------------+-------+
现在,当我逐渐从原型设计转向构建合适的软件时,我正在尝试思考这些方法中的任何一种如何适合 ORM 视角。它是每个 属性 的模型(如我的观点)还是所有属性的单个模型(如当前使用的 table)。 第三种选择可能是保留数据库原样并在视图之上构建模型(而不是真正的 tables),但这不是 ORM 的方式。
我什至考虑过将此数据集移动到 NoSQL 解决方案(例如 MongoDb),但我想不出克服双重视角问题的方法。
我承认这里既没有运行时也没有space性能问题,而且要存储和处理的数据量也可以忽略不计。一个小时内可能只有两个查询,每个查询都将特定流体的数据集加载到应用程序的内存中并在那里使用它(基于评估的插值和计算)。 所以如果你认为我对此压力过大,我会接受它。
否则,我想听听您的想法并考虑您可能提供的任何不同方法。我错过了什么吗?拆分 table 会产生的键冗余(流体和温度)怎么样?此外,其他设置了约束的人可能对此感兴趣。
每个带有 NULL 的 table 表示 "missing"("unknown" 或 "inapplicable")值对应于删除 NULLable 列并引入另一个 table 的架构使用原始的一些(超级)键并仅保留其中该列中不为 NULL 的行。
Null 支持更轻松的人类同时读取这些单独的相同(超级)密钥 table。但是它们使其他一切变得复杂,包括 meaning of a table(行进入或停留的 criterion/predicate),因此基础设计和查询组合。通常我们会尽快删除所有未粘贴到键以在最终输出中显示的 NULL。 (例如,OUTER JOIN 通常习惯上用于引入然后删除 NULL 以表达无 NULL EXCEPT/MINUS。)我们使用单独的 tables 的含义来表达 table 的含义NULL 和使用它的查询的含义。我们从组合的 NULL 视图中提取单独的 tables 以进行基本上任何处理。
直接的关系解决方案是单独的 tables。 SQL 传统是为一个 table。其他 SQL 理由是减少了合并 table 的 JOIN。但这仅适用于最终的人类可读输出!要处理那个 table,您无论如何都必须提取单独的视图。
PS
回复 "the redundancy of keys (fluid and temperature) that splitting the table would incur":相同(子行)值在列、table 或数据库中出现多次,不存在“redundancy”。当两个基础 table 或行做出相同的断言时,就会出现冗余。代入 criterion/predicate 的行给出 statement/proposition;当前行断言它的,不存在的行断言不是它的; table(命题)断言其存在行和不存在行的断言的合取。 (并且数据库(命题)断言其 table 的命题的合取。)此外,冗余不一定是坏事;在时间、space 和复杂性之间总是存在工程权衡。
PPS
ORM 有视图:延迟或惰性查询评估。由于您稍后可以在另一个查询中使用这样的查询,因此它就像一个视图一样。它是 ORM 查询语言而非 DBMS 查询语言中查询的命名表示。可以想象这可以用于更新命令(如果可能)以及查询。这取决于 DBMS/ORM。然而,视图更新基本上是一种方便,因为它总是可以用成分 tables.