在C

时间:2017-04-01 17:34:54

标签: c database file

我的代码执行以下操作

  1. 做了100次 打开一个新文件;写10M数据;关闭它
  2. 一起打开100个文件,读取并将其数据合并为更大的文件
  3. 循环多次执行步骤1和2
  4. 我想知道我是否可以保持100开,不打开和关闭它们太多次了。我可以做fopen w+ aabbcc...zzaabbcc..zz.........aabb...zz 。写完后我设置了开始读取的位置,读完后我将位置设置为开始写入,依此类推。

    问题是:

    1. 如果我在写完w / o结束后阅读,我们是否总是阅读所有书面数据
    2. 这会节省一些开销吗?文件打开和关闭必须有一些开销,但这个开销是否足以保存?
    3. 基于评论和讨论,我将讨论为什么我需要在工作中这样做。它也与我的其他帖子有关

      how to convert large row-based tables into column-based tables efficently

      我有一个生成结果流的计算。到目前为止,结果保存在行存储表中。该表有1M列,每列可长10M。实际上每列是计算产生的一个属性。在计算运行时,我转储并附加表的中间结果。中间结果可以是每列2或3个双值。我想尽快转储,因为它已经消耗了大约16M内存。计算需要更多的记忆。这最终得到如下表

       ref = FIRDatabase.database().reference()
       self.ref?.child("Entry").queryOrdered(byChild: "uid").queryEqual(toValue: uid).observeSingleEvent(of: .value, with: { [weak self] (snapshot) -> Void in
              guard let strongSelf = self else { return }
              print(snapshot)
      

      一行数据存储在一起。当我想逐列分析数据时,就会出现问题。所以我必须读取16个字节然后寻找下一行读取16个字节然后继续。有太多的搜索,它比所有列存储在一起要慢得多,所以我可以按顺序读取它们。

      我可以减少计算转储次数。但要使后期阅读更有效率。我可能希望将4K数据存储在一起,因为我假设即使我只读取16字节,每个fread也会默认获得4K。但这意味着我需要在内存中缓冲1M * 4k = 4G ...

      所以我在考虑是否可以将片段数据合并到更大的块中,如帖子所说

      how to convert large row-based tables into column-based tables efficently

      所以我想将文件用作离线缓冲区。如果每个文件包含1M的2个双打,我可能需要256个文件才能在合并后获得4K连续数据。在主要计算方面,这项工作可以作为异步方式完成。但我想确保合并开销很小,所以当它并行运行时,它可以在主计算完成之前完成。所以我提出了这个问题。

      我想这与基于列的数据库的构建方式非常相关。当人们创造它们时,他们是否有类似的问题?有没有关于它如何在创作中起作用的描述?

2 个答案:

答案 0 :(得分:2)

只要系统上打开的最大文件数允许,您就可以使用w+;这通常是255或1024,并且可以设置(例如在ulimit上的Unix上)。

但我不太确定这是值得的。

另一方面,每个10M的100个文件是1千兆字节;你可能想尝试一下RAM磁盘。或者使用大型文件系统缓存。

我怀疑通过分析您的具体问题结构可能会节省大量资金。为什么是100个文件?为何10 M?你在做什么样的“合并”?这100个文件总是以相同的顺序和相同的频率访问吗?是否可以将某些数据保存在RAM中,永远不会写入?

更新

所以,你有几个大的缓冲区,比如,

ABCDEFG...
ABCDEFG...
ABCDEFG...

你想要转动它们以便阅读

AAA...
BBB...
CCC...

如果您已经拥有总大小(即,您知道要写入10 GB的数据),则可以使用两个文件执行此操作,预先分配文件并使用fseek()写入输出文件。使用内存映射文件,这应该非常有效。实际上,行Y,X列为1,000,000,已被转储到文件Y.dat中的地址16 * X处;你需要把它写成16 *(Y * 1,000,000 + X)到largeoutput.dat

实际上,即使在第一次计算时也可以写入数据。或者您可以通过管道进行两个进程通信,一个计算,一个写入行列和列行文件,以便您可以监视每个进程的性能。

坦率地说,我认为增加更多内存和/或快速I / O层(SSD可能?)可以让你获得同样的优势。您的时间也是如此,在完成这项工作后,内存仍然可用。

答案 1 :(得分:0)

是。您可以在不执行开 - 关 - 打开周期的情况下保持打开100个文件。但是,大多数系统对打开文件的数量都有限制。

如果我在写完w / o结束后阅读,我们是否总是阅读所有书面数据

这取决于你。您可以在文件中的任何位置执行fseek goto并从中读取数据。它一直是你和你的逻辑。

这会节省一些开销吗?文件打开和关闭必须有一些开销,但这个开销是否足以保存?

这肯定会节省一些开销,比如额外的不必要的I / O操作,并且在某些系统中,您写入文件的内容不会立即刷新到物理文件,它可能会被定期缓冲和刷新,或者在fclose的时间。

所以,这样的开销会被保存,但是,真正的问题是你通过节省这些开销来实现什么?它如何适合您的应用程序的整体情况?这是在决定逻辑之前必须进行的调用。

相关问题