sqlite 循环列值的最佳数据库结构[已关闭]

djmepvbi  于 2022-11-14  发布在  SQLite
关注(0)|答案(1)|浏览(135)

已关闭。这个问题是opinion-based。它目前不接受答案。
**想要改进这个问题吗?**更新问题,以便editing this post可以用事实和引用来回答它。

6天前关门了。
Improve this question
我有实验数据要存储。实验可以用不同的设置运行,比如说设置a和b,它们可以设置为不同的值。该实验在每个设置下运行100.000次。如何针对此数据结构优化我的表?
朴素的实现是一个具有列名称setting asetting bresult of experiment的表,并添加每行的数据。例如,可以将设置a设置为值(1, 2, 3),并将b设置为(0.1, 0.01)

(_ROWID_), setting a, setting b, result
(0,) 1 0.1 res_1
(1,) 1 0.1 res_2
(2,) 1 0.1 res_3
... 
(n,) 2 0.1 res_n
(n+1,) 2 0.1 res_n+1
... 
(k,) 3 0.1 res_k
(k+1,) 3 0.1 res_k+1
... 
(l,) 1 0.01 res_l
(l+1,) 1 0.01 res_l+1
... etc.

索引l > k > n > 0是自动递增行id的主键。不太理想,但很容易实现。我发现数据检索速度很慢。这种实现既不利于内存(因为setting asetting b重复多次,因此应该是指向一组结果的指针),也不利于搜索性能(表是无序的,而搜索应该返回有序的数据)。
另一种选择是为每组setting asetting b(命名为table_a_b)创建一个子表,并为指向每个子表的父表创建一个“目录”。则可以存储result of experiment而不必引用setting asetting b。然而,这使得查询变得更加困难。
或者聚集索引,如果我理解正确的话,它们形成了一个执行类似工作的b-树。
对于我所描述的用例,提到的三个选项的优点和缺点是什么?

9wbgstp7

9wbgstp71#

首先,如果您的设置真的像您的示例所示的那样简单(一些数字),那么您现在拥有的数据设计是完全可用的。它的最大优势是非常简单。是的,你有一些重复的数字。但是,即使有数百万行,您的表也不会压倒现代机器的RAM和SSD/硬盘驱动器。如果到了在表中查找内容太慢的地步,可以添加索引。(简单就是好!由过于复杂的数据存储方案引起的数据解释错误是糟糕的!)
但是,你说得对,这是次优的。你走上了正确的道路。SQL数据设计是关于实体关系的。在我看来,你在你的物质世界里有两个实体。一个是setting,另一个是result。实体之间的关系是这样的:每个setting有零个或多个results
因此,为自己创建一个settings表,每个设置一行,包含其属性的列。在您的示例中,它们是a和b。

CREATE TABLE settings (
  settings_id  INTEGER PRIMARY KEY, 
  a            INTEGER NOT NULL,
  b            REAL NOT NULL,
  UNIQUE (a, b)
);

UNIQUE行防止您在该表中创建重复行。这可能是可取的,也可能是不可取的。(只有你知道)。如果它不受欢迎,请将其排除在您的表定义之外。
然后为自己制作一张results表,就像这样。对于构成结果一部分的每个观察,您都将有一个专栏。如果我是您,我会添加一个RESULT_TIME列,这样您就可以知道什么时候进行了观察。第二列包含设置的settings_id

CREATE TABLE results (
  results_id     INTEGER PRIMARY KEY, 
  settings_id    INTEGER,
  results_time   DATETIME,
  obs1           REAL,
  obs2           TEXT,
  obs3           INTEGER
);

然后,一旦填充了这些表,您就可以运行如下查询。

SELECT settings.settings_id, settings.a, settings.b,
       COUNT(results.results_id) number_of_runs,
       MIN(results.results_time) first_result_time,
       MAX(results.results_time) last_result_time,
       AVG(results.obs1) mean_obs1
  FROM settings
  JOIN results ON settings.settings_id = results.settings_id
 GROUP BY settings.settings_id, settings.a, settings.b

(当然,您可以使用当前的数据设计运行类似的查询。)
填充这些表是一个诀窍。在插入每个新的results行时,您必须使用一些代码来...

  • 查找相应settings行的settings_id
  • 如果不存在,则插入它,并使用last_insert_rowid()函数获取其id。
  • 然后使用该ID插入您的results行。

您没有提到您使用的任何编程语言(python?Java?)所以很难给你具体的建议。

相关问题