在PostgreSQL中表示稀疏数据矩阵的最佳方法是什么?我看到的两个明显的方法是:
将数据存储在一个表中,每个表都包含一个单独的列(可能是数百万个),但未使用的功能的默认值为NULL。这在概念上非常简单,但我知道在大多数RDMS实现中,这通常是非常低效的,因为NULL值通常占用一些空间。但是,我读了一篇文章(遗憾的是找不到它的链接),声称PG没有占用NULL值的数据,使其更适合存储稀疏数据。
创建单独的“行”和“列”表,以及用于链接它们并在该行存储列值的中间表。我相信这是更传统的RDMS解决方案,但与之相关的复杂性和开销更多。
我还发现了PostgreDynamic,它声称可以更好地支持稀疏数据,但我不想仅仅为了这个功能而将整个数据库服务器切换到PG分支。
还有其他解决方案吗?我应该使用哪一个?
答案 0 :(得分:13)
我假设您正在考虑数学上下文中的稀疏矩阵: http://en.wikipedia.org/wiki/Sparse_matrix(这里描述的存储技术用于存储器存储(快速算术运算),而不是持久存储(低磁盘使用)。)
由于人们通常在客户端而不是服务器端对此矩阵进行操作,因此SQL-ARRAY []是最佳选择!
问题是如何利用矩阵的稀疏性?这是一些调查结果。
设定:
竞争方法:
bit varying(xx)
),描述矩阵中非零元素的位置。 (一个双精度比一位大64倍。理论上(忽略开销)如果< = 98%非零,这个方法应该是改进;-)。)服务器端压缩被激活。(使用第二个索引-ARRAY []索引非零元素并不是很有希望,因此没有经过测试。)
结果:
结论: 从EXTENDED / MAIN存储参数开始。如果您有空闲时间调查您的数据并使用我的测试设置与稀疏级别。但效果可能低于您的预期。
我建议总是使用矩阵序列化(例如行主要顺序)加上两个整数列作为矩阵维度NxM。由于大多数API使用文本SQL,因此您可以为嵌套的“ARRAY [ARRAY [..],ARRAY [..],ARRAY [..],ARRAY [..],..]”节省大量网络流量和客户端内存。 !!!
Tebas
CREATE TABLE _testschema.matrix_dense
(
matdata double precision[]
);
ALTER TABLE _testschema.matrix_dense ALTER COLUMN matdata SET STORAGE EXTERN;
CREATE TABLE _testschema.matrix_sparse_autocompressed
(
matdata double precision[]
);
CREATE TABLE _testschema.matrix_sparse_bitmap
(
matdata double precision[]
bitmap bit varying(8000000)
);
将相同的矩阵插入所有表格。具体数据取决于特定表。 由于未使用但已分配的页面,请勿更改服务器端的数据。或做一个VACUUM。
SELECT
pg_total_relation_size('_testschema.matrix_dense') AS dense,
pg_total_relation_size('_testschema.matrix_sparse_autocompressed') AS autocompressed,
pg_total_relation_size('_testschema.matrix_sparse_bitmap') AS bitmap;
答案 1 :(得分:7)
我想到了一些解决方案,
1)将您的功能分成通常设置在一起的组,为每个组创建一个表,与主数据具有一对一的外键关系,只在查询时需要加入表
2)使用EAV反模式,使用主表中的外键字段以及字段名和值列创建“功能”表,并将功能存储为该表中的行而不是属性在主表中
3)与PostgreDynamic的工作方式类似,为主表中的每个“列”创建一个表(它们为这些表使用单独的命名空间),并创建函数以简化(以及有效索引)访问和更新这些表格中的数据
4)使用XML或VARCHAR在主数据中创建一个列,并在其中存储一些表示数据的结构化文本格式,使用功能索引创建数据索引,编写更新数据的函数(或使用XML函数,如果您使用该格式)
5)使用contrib / hstore模块创建一个类型为hstore的列,该列可以保存键值对,并且可以被索引和更新
6)住着很多空地
答案 2 :(得分:2)
当NULL值为NULL时,NULL值将不占用空间。它将在元组头中的位图中占用一位,但无论如何都会存在。
但是,系统无法处理数百万列,期间。理论上最多有一千多个,IIRC,但你真的不想走那么远。如果你真的需要那么多,在一张桌子里,你需要采用EAV方法,这基本上就是你在(2)中所说的。
如果每个条目只有相对较少的密钥,我建议您查看“hstore”contrib模块,它可以非常有效地存储此类数据,作为第三种选择。它在即将推出的9.0版本中得到了进一步的增强,因此,如果您远离生产部署,您可能需要直接查看该版本。但是,它在8.4中也是值得的。它确实支持一些非常有效的基于索引的查找。绝对值得研究。
答案 3 :(得分:2)
我知道这是一个旧线程,但MadLib为Postgres提供稀疏矢量类型,以及几种机器学习和统计方法。