我需要在磁盘上存储一个非常简单的数据结构 - Point
。它的字段只是:
Moment
- 64位整数,表示高精度的时间
EventType
- 32位整数,对另一个对象的引用
Value
- 64位浮点数
要求:
1)这对(Moment
+ EventType
)是Point
的唯一标识符,因此我怀疑它是表的复合主键
2)有大量的Points
。高达50亿(1-2 TB的磁盘空间)。所以格式必须尽可能小。
3)该表的典型和几乎单一用法是按照完整Points
和EventType
的范围检索(或创建一个)数百万Moments
的视图。
问题:
选择哪种RDBMS?为什么?
Points
表的最佳sql定义是什么?
以下对我的想法的评论也很感激
我的研究:
我是RDBMS领域的全新手,但我听说过很多关于SQLite的内容。我不需要一个庞大的专业系统,包括PostgreSQL或MSSQL等所有工具,功能和扩展。另外我觉得我不需要服务器而不是简单的“嵌入式”数据库文件,因此SQLite的选择看起来是最佳的。另一个具有嵌入式数据库功能的优秀RDBMS是Firebird,但我被SQLite的动态类型范式所诱惑。看起来它可以节省我在磁盘上的空间,因为整数字段可以以“较小”的形式存储(1,2,3,4,6字节)。
但很快就出现了问题。
首先,当主键是复合键时,SQLite会创建特殊的ROWID
列(64位长度):
CREATE TABLE points (
moment integer not null,
event_id integer not null,
value numeric not null,
PRIMARY KEY (moment, event_id)
);
这意味着桌子浪费了近40%的空间。
我找到了关于"The WITHOUT ROWID Optimization"的好文章。但它只能在3.8.2版本的SQLite(2013年12月)中使用。等待我需要的ADO.NET提供程序是不合适的。
另一个问题是SQLite对表使用B-tree。我不确定,但看起来选择数据范围效率低下。我的主要任务是根据主键的范围选择一个Points
的大块,所以看起来SQLite会很糟糕。
未来的研究对我来说似乎太难了(至少在今天)。期待有经验的人的帮助。
答案 0 :(得分:1)
B树是选择数据范围的最有效组织。
如果您搜索常量event_id
值和一系列moment
值,则仅当event_id
是第一列时,两列索引才可用于两个查找指数:
CREATE TABLE points (
event_id INTEGER NOT NULL,
moment INTEGER NOT NULL,
value NUMERIC NOT NULL,
PRIMARY KEY (event_id, moment)
);
您应该尝试使用版本3.8.2,以便可以使用WITHOUT ROWID优化 developers可能很高兴有人会测试这个功能,并给你一个编译的预发布版本。
答案 1 :(得分:-1)
我认为如果您的表将使用多个用户,则不应使用嵌入式数据库
那么Oracle - 由索引组织的表(也许是按事件)+按范围划分
或按范围划分的MySql
如果你的应用程序真的是一个用户,也许你可以使用文件系统?
像分区表这样的东西
您可以创建名称与范围相关的文件夹
并创建名称与event_id相关的文件,因此您只需要在文件中存储时刻+数据
更多例如你的时刻
201311141820001234567890123456
您可以创建名称为2013111418的文件夹,并仅在文件中存储时刻和数据的一部分
20001234567890123456,数据
20001234567890123457,数据