Database design 构建一个;稀疏的;数据表+;ORM(&x2B;NoSQL?)
在开发一个热力学模拟软件(C++中)时,我需要存储不同温度下的流体属性。这些数据点用于构建一个简单的插值函数,以便在我们没有完整实验数据的温度下评估属性值 流体仅通过其名称和浓度(%)来识别(后者通常不相关)。如果你好奇的话,你会对四个特性感兴趣:质量密度、动态粘度、比热容量和导热系数。对于任何其他用途,这些只是4个数字属性,称它们为A、B、C和D。 特定流体的函数如下:Database design 构建一个;稀疏的;数据表+;ORM(&x2B;NoSQL?),database-design,orm,null,relational-database,non-relational-database,Database Design,Orm,Null,Relational Database,Non Relational Database,在开发一个热力学模拟软件(C++中)时,我需要存储不同温度下的流体属性。这些数据点用于构建一个简单的插值函数,以便在我们没有完整实验数据的温度下评估属性值 流体仅通过其名称和浓度(%)来识别(后者通常不相关)。如果你好奇的话,你会对四个特性感兴趣:质量密度、动态粘度、比热容量和导热系数。对于任何其他用途,这些只是4个数字属性,称它们为A、B、C和D。 特定流体的函数如下:(a,B,C,D)=f(T),其中T是温度 目前,它是一个SQLite3数据库,流体表如下所示: +----+-------+
(a,B,C,D)=f(T)
,其中T是温度
目前,它是一个SQLite3数据库,流体表如下所示:
+----+-------+---------------+
| id | name | concentration |
+====+=======+===============+
| 1 | Water | 100 |
+----+-------+---------------+
| 2 | ..... | ... |
还有属性表:
+----------+-------------+---------+-----------+--------------+----------+
| 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的直观显示
然而,在代码中,插值是为每个属性分别进行的。此外,由于我不能使用空值,因此并非所有温度(行)都与所有属性相关。为了适应代码的观点,我创建了四个相同的视图——每个属性一个。例如:
+----+-----------+---------------+-------------+-------+
| 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的视角。它是每个属性的模型(如我的视图)还是所有属性的单一模型(如当前使用的表)。
第三种选择可能是保持数据库不变,在视图(而不是实际表)上构建模型,但这不是ORMs的方式
我甚至考虑过将这个数据集迁移到NoSQL解决方案(例如MongoDb),但我想不出一种方法来克服双视角问题
我承认,这里既没有运行时性能问题,也没有空间性能问题,而且要存储和处理的数据量可以忽略不计。一小时内可能会有两个查询,每个查询都会将特定流体的数据集加载到应用程序的内存中,并在内存中进行处理(插值和基于评估的计算)。
所以如果你认为我对这件事过分紧张,我会接受的
否则,我想听听你的想法,考虑一下你可能提供的不同方法。我错过什么了吗?拆分表时会产生的键冗余(流体和温度)如何?另外,其他设置了约束的人可能会对此感兴趣。每个带有NULL的表都表示“缺少”(“未知”或“不适用”)值,对应于一个模式,该模式删除了可为NULL的列,并引入了另一个表,该表具有原始的某些(超级)键,并且只保留该列中不为NULL的行 空值支持更方便的人工同时读取这些单独的相同-(超级)键表。但它们会使其他一切复杂化,包括(一行进入或退出的条件/谓词),从而导致基本设计和查询组合。通常,我们会尽快删除所有未粘贴到键上的空值,以便在最终输出时显示。(例如,通常习惯性地使用外部联接来引入空值,然后删除空值,以表示除/减以外的空值。)我们在用空值表示表的含义以及使用空值表示查询的含义时,都使用了单独表的含义。我们从组合的空视图中提取单独的表,基本上用于任何处理 简单的关系解决方案是单独的表。SQL传统是针对一个表的。其他SQL对正是由于合并表而减少的联接。但这只适用于最终的人类可读输出!要处理一个表,您必须提取出单独的视图 PS
关于“拆分表时会产生的键冗余(流体和温度)”:在一列、表或数据库中,相同(subrow)值不会出现多次。当两个基表或行做出相同的断言时,就会出现冗余。替换为条件/谓词的行给出一个语句/命题;当前行声明its,不存在的行声明非its;表(命题)断言其当前行和不存在行的断言的连接。(并且数据库(命题)断言其表命题的连接。)此外,冗余并不一定是坏的;在时间、空间和复杂性之间总是存在工程权衡 PPS
ORM有视图:延迟或延迟查询求值。因为以后可以在另一个查询中使用这样的查询,所以它的行为就像一个视图。它是ORM查询语言而不是DBMS查询语言中查询的命名表示。这可以想象为更新命令(如果可能)和查询。这取决于DBMS/ORM。然而,视图更新基本上是一种方便,因为它总是可以用对组成表的更新来表示。因此,多亏了您的重要输入,我似乎是在倒退(关系模型方面)。我很高兴我问得够早了。此处未直接解决的唯一问题是拆分表时会产生的键冗余(流体和温度)。然而,在阅读了一些关于空标记的争论之后,我现在认为保留表是错误的。至于视图和ORM,在SQLite的情况下,它只支持只读视图,延迟求值可能与视图类似。就我个人而言,我确实更喜欢只读视图。尽管如此,其他RDBMs以及关系模型都支持视图上的写操作。延迟评估是否有不足之处?(1)感谢您的出色回复。(2) 我同意,在许多方面,观点只是一种观点