Ser*_*ndt 4 schema sqlite time-series-database
这是情况:
我想,按照惯例,人们会将所有时间序列数据转储到单个表中,并带有标识每个数据点来源的文本字段。
但是,我想知道为每个时间序列数据源创建一个单独的表是否会更有效?通过消除重复的文本字段,SQLite 数据库的文件大小最终会小很多吗?查询会运行得更快吗?
或者我应该完全避免为每个来源创建表格以及出于什么原因?
数据库不会很大,这可能保证在 MySQL 上使用 SQLite。除了整数时间戳,还有四个整数字段。每 3 分钟进行一次测量,但它可以轻松运行一年或更长时间。部分设计最终可能会出现在闪存容量非常有限(64Mbit)的嵌入式设备中,因此我最初对 SQLite 感兴趣。但是,我愿意接受其他建议。
就个人而言,我讨厌丢弃可能有用的数据。我会为源创建一个表,并将source_id
其作为源表的外键包含在时间序列表中。这应该占用更少的空间,但仍保留源信息(不需要多个相同的表)。
我整理了一个简短的例子;请参阅此db-fiddle 链接。
这是我的示例中的代码:
CREATE TABLE source
( source_id INTEGER PRIMARY KEY ASC
,name varchar(10)
);
CREATE TABLE time_series
( series_id INTEGER PRIMARY KEY ASC
,timestamp INTEGER
,value1 INTEGER
,value2 INTEGER
,value3 INTEGER
,source_id INT
,FOREIGN KEY (source_id) REFERENCES source(source_id)
);
INSERT INTO source (name)
VALUES ('AAAA'), ('BBBB'), ('QZQZ');
INSERT INTO time_series (timestamp, value1, value2, value3, source_id)
VALUES (12345678, 100, 105, 110, 1)
,(12345681, 105, 105, 105, 1)
,(12345684, 110, 105, 100, 1)
,(12345678, 9, 27, 81, 3)
,(12345681, 27, 81, 243, 3)
,(12345684, 81, 243, 729, 3)
;
SELECT * FROM source;
SELECT s.name as source, timestamp, value1, value2, value3
FROM source s INNER JOIN time_series ts ON (s.source_id = ts.source_id)
ORDER BY source, timestamp
;
Run Code Online (Sandbox Code Playgroud)
我应该注意到我通常不使用 SQLite。正如您在对我的原始评论的回复中指出的那样,默认情况下,SQLite 在每个表中维护一个 64 位整数行 ID 列。我已经设置了示例中的表,以使用该行 ID 值作为每个表的主键。如果我正确阅读了文档,那么外键列应该足够大以保存主键中的值。假设你没有手动插入一个source_id
很大的,我相信source_id
在time_series
表中应该只需要 1 个字节。
您可能想要UNIQUE
在source_id
and上放置一个索引timestamp
(您几乎肯定应该对它们有某种索引);据推测,您永远不应该在同一来源和同一时间拥有两个条目。正如 Serge Stroobandt 所指出的,这甚至可能是主键。但是,由于 SQLite 无论如何都会创建一个唯一的行 ID 值,因此我倾向于将其作为键。如果您真的想使用source_id
和timestamp
作为主键,请考虑创建 table WITHOUT ROWID
。