如果您的矩阵真的很稀疏(即节点只有少量互连),那么您将从RDBMS(如Oracle,PostgreSQL或SQL Server)获得相当高效的存储。基本上你会有一个包含两个字段(行,列)和一个索引或键的表。
单向设置主键(取决于您是否主要按行或列进行查询),并且相反地在字段上创建另一个索引。这将只存储连接存在的数据,并且它将与图中的边数成正比。
索引将允许您高效地检索行或列,并始终保持同步。
如果每个节点有10,000个节点和10个连接,则数据库将只有100,000个条目。每节点100个ednges将有1,000,000个条目等等。对于稀疏连接,这应该相当有效。
背的-FAG分组估计
该表将基本上具有行和列的字段。如果聚集索引变为(行,列,值),则另一个覆盖索引将变为(列,行,值)。如果增加和删除是随机的(即,不按行或列进行分批),I/O将近似于表格的两倍。
如果按行或列对插入进行批处理,那么您将在其中一个索引上获得更少的I/O,因为记录物理上位于其中一个索引中。如果矩阵实际上是稀疏的,那么这个邻接列表表示是迄今为止最紧凑的存储方式,这比将其存储为二维数组要快得多。
具有64位值的10,000 x 10,000矩阵需要800MB加上行索引。更新一个值需要写入每个写入至少80k(写出整行)。如果数据可以按插入行分组,则可以按行优化写入。如果插入是实时和随机的,那么您将为每个插入写出80k行。
实际上,这些写操作会有一定的效率,因为这些写操作都将被写入大部分连续的区域,具体取决于您的NoSQL平台如何物理存储其数据。
我不知道如何稀疏连接,但如果每个节点平均有100个连接,那么您将拥有1,000,000条记录。这将大约每行16字节(Int4行,Int4列,Double值)加上聚集表和覆盖索引的几个字节开销。这种结构大约需要32MB +的存储空间。
假设插入不是行或列排序,更新行或列上的单个记录将导致两个单个磁盘块写入(8k,实际上是一个段)用于随机访问。
将100万个随机排序的条目添加到数组表示会导致大约80GB的写入量+少量开销。向邻接列表表示中添加1m条目会导致大约32MB的写入(实践中为16GB,因为整个数据块将写入每个索引叶节点),再加上一点开销。
对于该级别的连接(每个节点有10,000个节点,100个边),邻接列表 在存储空间中可能更高效,也可能在I/O中更高效。您将从该平台获得一些优化,因此某种基准可能适用于查看哪些在实践中更快。
我不确定Math.SE网站是否会知道这个问题的答案... – Blender