在服务器上存储100,000多个CSV文本文件的最佳方法?

时间:2014-10-09 09:15:30

标签: sqlite file storage scalability

我们有一个应用程序需要存储数千个相当小的CSV文件。 100,000+并且每年增长相同的数量。每个文件包含大约20-80KB的车辆跟踪数据。每个数据集(或文件)代表单个车辆行程。

我们目前正在SQL Server中存储此信息,但数据库的大小变得有点笨拙,我们只需要一次访问一个文件的旅程数据(因此需要批量查询或以其他方式存储在关系数据库中不需要)。由于在插入或删除数据时重建或更新索引所花费的时间,因此我们添加更多轨道时数据库的性能会下降。

我们正在考虑3个选项:

  1. 我们可以使用SQL的FILESTREAM功能将数据外部化为文件,但我之前没有使用过此功能。 Filestream还会为每个数据库对象(blob)生成一个物理文件吗?

  2. 或者,我们可以将文件单独存储在磁盘上。那里 在3年多之后,它们可能会结束50万。请问 NTFS文件系统可以用这个量处理好吗?

  3. 如果有大量文件存在问题,我们是否应考虑将数据集/文件分组到一个小型数据库(一个用户)中,以便每个用户?是否有一个非常轻量级的数据库,如SQLite,可以存储文件?

  4. 还有一点:数据具有高度可压缩性。压缩文件会将它们缩小到原始大小的10%。我想尽可能利用压缩来最小化使用的磁盘空间和备份大小。

2 个答案:

答案 0 :(得分:2)

我有一些想法,这是非常主观的,所以你的里程和其他读者的里程可能会有所不同,但希望即使其他人想要提出不同的观点,它仍然会为你滚动。

首先,我看到包含太多文件的文件夹存在性能问题。一个项目通过创建256个目录来解决这个问题,这些目录名为00,01,02 ... fd,fe,ff,并且在其中每个目录中还有256个具有相同命名约定的目录。这可能会将您的500,000个文件划分为65,536个目录,每个目录中只有几个 - 如果您使用一个好的哈希/随机生成器将它们展开。此外,文件名很短,无法存储在您的数据库中 - 例如32/af/file-xyz.csv。毫无疑问,有人会咬我的头,但我觉得一个目录中有10,000个文件可以继续使用。

其次,100,000个80kB的文件相当于8GB的数据,这些日子真的不是很大 - 实际上是一个小型的USB闪存驱动器 - 所以我认为任何关于压缩的论点都不是那么有效 - 存储很便宜。但重要的是备份。如果你有500,000个文件,你有很多“inode”要遍历,我认为统计数据曾经是许多备份产品每秒只能遍历50-100个inode - 所以你将等待很长时间。根据您可以容忍的停机时间,最好让系统脱机并从原始的块设备备份 - 比如100MB / s,您可以在80秒内备份8GB,我无法想象传统的文件基于备份的备份可以接近。备选方案可以是允许快照的文件系统,然后您可以从快照备份。或者是一个镜像文件系统,它允许您拆分镜像,从一个副本备份然后重新加入镜像。

正如我所说,非常主观,我相信其他人会有其他想法。

答案 1 :(得分:1)

我在使用混合方法的应用程序上工作,主要是因为我们希望我们的应用程序能够在免费版本的SQL Server中工作(在小型安装中)......并且文件负载会让我们超过顶层很快。我们有大量的文件 - 大型安装中的数千万。

我们考虑过你所枚举的相同场景,但我们最终决定做的是拥有一系列中等大小(2gb)的内存映射文件,这些文件包含将成为不透明blob的潜在文件。然后,在数据库中,blob由blob-id(未压缩blob的sha1哈希)键入,并具有container-file-id,offset,length和uncompressed-length的字段。 blob-referencing表中还有一个“已发布”标志。因为散列忠实地表示内容,所以blob只写一次。修改后的文件会产生新的哈希值,并将它们写入blob存储区中的新位置。

在我们的例子中,blob不是一致的文本文件 - 实际上,它们是所有类型的文件块。使用滚动哈希函数将大文件分解为大约64k块。我们尝试使用lz4压缩来压缩每个blob(这是快速压缩的方式 - 并且在有效不可压缩数据上快速中止)。

这种方法效果很好,但并不是轻率推荐的。它会变得复杂。例如,面对已删除的内容修饰容器文件。为此,我们选择使用稀疏文件,并告诉NTFS已删除blob的范围。交易需求更加复杂。

db-to-blob-store的所有goop都是c#,内存映射文件有一点间互操作。你的场景听起来很相似,但要求不高。我怀疑你可以在没有内存映射的I / O复杂情况下逃脱。