在没有任何答案的情况下,我自己进一步探讨了这个问题。
似乎用户定义的函数可以处理所有基本类型,包括 bytea
和smallint[]
,因此这对表示形式的选择影响不大。
我在具有原始配置的Windows 7便携式计算机上本地运行的PostgreSQL 9.4服务器上尝试了几种不同的表示形式。存储该实际信号数据的关系如下。
整个文件的大对象
CREATE TABLE BlobFile (
eeg_id INTEGER PRIMARY KEY,
eeg_oid OID NOT NULL
);
每通道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)
);
每个时期每个频道的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)
);
每个时期的SMALLINT 2D数组
CREATE TABLE EpochArray (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
signals SMALLINT[][] NOT NULL,
PRIMARY KEY (eeg_id, epoch)
);
每个时期的BYTEA数组
CREATE TABLE EpochBytea (
eeg_id INT NOT NULL,
epoch INT NOT NULL,
signals BYTEA NOT NULL,
PRIMARY KEY (eeg_id, epoch)
);
然后,我通过Java JDBC将选择的EDF文件导入到每个关系中,并比较每次上载后数据库大小的增长。
这些文件是:
- 文件A:16个通道的2706个时期,每个通道1024个样本(每个时期16385个样本),85 MB
- 文件B:18个通道的11897个时期,每个通道1024个样本(每个时期18432个样本),418 MB
- 文件C:20个通道的11746个时期,每个通道64到1024个样本(每个时期17088个样本),382 MB
就存储成本而言,以下是每种情况下以MB为单位的大小:
相对于原始文件大小,大对象大约大30-35%。相比之下,将每个时期存储为BYTEA或SMALLINT [] []则小于10%。以BYTEA或SMALLINT []的形式将每个通道存储为一个单独的元组可以增加40%,因此,与存储为大对象相比,这并不差。
我最初没有意识到的一件事是PostgreSQL中的“多维数组必须具有每个维的匹配范围” 。这意味着SMALLINT[][]
仅当一个时期中的所有通道具有相同数量的样本时,该表示才起作用。因此,文件C无法处理该EpochArray
关系。
就访问成本而言,我还没有解决这个问题,但是至少在最初插入数据方面,最快的表示形式是EpochBytea
和BlobFile
,而EpochChannelArray
最慢的表示形式是前两个表示形式的三倍。