bel*_*daz 9 postgresql datatypes blob bytea
我希望将大型 (100Mb -- 1 GB) 多通道时间序列数据导入 PostgreSQL 数据库。数据来自EDF 格式的文件,这些文件将数据分块成“记录”或“时期”,每个“记录”或“时期”通常为几秒钟。每个时期的记录将每个数据通道的信号保存为短整数的顺序数组。
我被要求将文件存储在数据库中,在最坏的情况下存储为 BLOB。鉴于此,我想研究可以让我对数据库中的数据做更多事情的选项,例如促进基于信号数据的查询。
我最初的计划是将数据存储为每个纪元记录一行。我想要权衡的是是否将实际信号数据存储为 bytea 或 smallint[](甚至 smallint[][])类型。有人可以推荐一个吗?我对存储和访问成本感兴趣。用法很可能是插入一次,偶尔读取,从不更新。如果一个更容易包装为自定义类型,以便我可以添加用于分析比较记录的函数,那就更好了。
毫无疑问,我缺乏细节,所以请随时对您希望我澄清的内容添加评论。
bel*_*daz 11
在没有任何答案的情况下,我自己进一步探讨了这个问题。
看起来用户定义的函数可以处理所有基本类型,包括 bytea
and smallint[]
,所以这不会对表示的选择产生太大影响。
我在 PostgreSQL 9.4 服务器上尝试了几种不同的表示,该服务器在 Windows 7 笔记本电脑上本地运行,具有 vanilla 配置。存储实际信号数据的关系如下。
整个文件的大对象
CREATE TABLE BlobFile (
eeg_id INTEGER PRIMARY KEY,
eeg_oid OID NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
每个通道的 SMALLINT 数组
CREATE TABLE EpochChannelArray (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
channel INT,
signal SMALLINT[] NOT NULL,
PRIMARY KEY (eeg_id, epoch, channel)
);
Run Code Online (Sandbox Code Playgroud)
每个 epoch 每个通道的 BYTEA
CREATE TABLE EpochChannelBytea (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
channel INT,
signal BYTEA NOT NULL,
PRIMARY KEY (eeg_id, epoch, channel)
);
Run Code Online (Sandbox Code Playgroud)
每个时期的 SMALLINT 二维数组
CREATE TABLE EpochArray (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
signals SMALLINT[][] NOT NULL,
PRIMARY KEY (eeg_id, epoch)
);
Run Code Online (Sandbox Code Playgroud)
每个纪元的 BYTEA 数组
CREATE TABLE EpochBytea (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
signals BYTEA NOT NULL,
PRIMARY KEY (eeg_id, epoch)
);
Run Code Online (Sandbox Code Playgroud)
然后,我通过 Java JDBC 将精选的 EDF 文件导入到每个关系中,并比较每次上传后数据库大小的增长。
这些文件是:
在存储成本方面,以下是每种情况下占用的大小(以 MB 为单位):
相对于原始文件大小,大对象大约大 30-35%。相比之下,将每个 epoch 存储为 BYTEA 或 SMALLINT[][] 的大小不到 10%。将每个通道存储为单独的元组会增加 40%,无论是 BYTEA 还是 SMALLINT[],所以并不比存储为大对象差多少。
我最初没有意识到的一件事是PostgreSQL中的“多维数组必须具有每个维度的匹配范围” 。这意味着该SMALLINT[][]
表示仅在一个 epoch 中的所有通道具有相同数量的样本时才有效。因此文件 C 无法处理该EpochArray
关系。
在条款接入成本,我还没有与此发挥各地,但至少在插入数据方面最初最快的表示是EpochBytea
和BlobFile
,用EpochChannelArray
最慢,需要大约3倍,只要是前两种。
归档时间: |
|
查看次数: |
921 次 |
最近记录: |