好的,我已经搜索了这个,并阅读了关于在[MySQL]数据库中存储二进制数据的几点观点。一般来说,我认为这是一个坏主意,并试图避免它,支持传统的文件传输,只是将文件的引用存储在数据库中。
但是,我正在开发一个项目,该项目需要与远程/云数据库进行数据库同步,不仅适用于文件,还适用于设置和其他用户内容。出于这个原因,我认为这可能是数据库中二进制存储的适当情况。
我已经为数据库同步编写了一个通用系统,它可以很好地使用Reflection和XML。我也(以我的直觉)将文件存储集成到这个系统中。再次,它运行良好 - 我将文件切换到64Kb BLOB并将它们存储在一个表中,带有file_id引用(链接到包含元数据的单独表,如文件名/大小/ mime类型)。
这使我能够在连接可用时发送碎片,并允许我限制每个请求大小以保持平稳运行。
到目前为止,我还没有发现任何问题,并且已经成功导入并传输了超过1GB的数据(超过10-15个文件/ 16000行),但我担心它的可扩展性 - 它会减慢吗?一旦有20gb +数据,或者MySQL可以处理它,只要我的查询结构良好?
我决定将数据存储在数据库中的另一个原因是我认为如果空间不足,我可以简单地向MySQL添加另一个HDD /存储设备,以期有效扩展/复制等。
我非常感谢任何观点或评论是关于这是一个好的还是坏的方法,并且我错过了在生产环境中曾经可能会看到的任何明显的问题?
编辑:我忘了提一下,文件大小可以从1KB到~1GB
[粗略]结论 首先:非常感谢那些提出深思熟虑的答案的人。在这里选择接受的答案非常困难,因为每个人都可以提供一些体面的东西。
最后(尽管我的希望),我已经决定纯粹的MySQL存储服务器充其量只是一个好的解决方案(我仍然不禁想知道为什么他们打扰包括BLOB类型)。
作为替代方案,我在@Nick Coons文件系统方法和@ tadman使用轻量级键/值数据库引擎(如leveldb)的混合建议之间徘徊。如果在这个项目中使用leveldb的实用性不是问题,这很可能是我将努力的方法。
我在此基础上接受了塔德曼的回答;他的回答对我的情况也是最适用和最有用的。
话虽如此,对于那些感兴趣的人:到目前为止,我只使用MySQL获得了很多成功。我已经测试了一个存储超过15gb二进制数据的表,没有任何明显的负面影响,从大表中插入/检索数据(仔细查询)。但是,我确信这仍然是非常低效的,所提到的任何替代方法都会明显更好。
答案 0 :(得分:3)
简答:
我不确定是否有一种强硬的方式来回答这个问题。你提到的文件从1KB到1GB。我不会在数据库中存储二进制数据,如果它接近1KB,那就是1GB。如果是偶然的话,我可以在数据库中存储几个字节的二进制数据,但是任何大量的数据,特别是不需要搜索的数据,都应该存储在文件系统中:
当您将数据存储在数据库中时,无论如何都要将其存储在文件系统中,您只需添加另一层(数据库)即可。这一层需要付出代价,因此弥补差异应该是有益的。如果您要存储数据以便可以根据它进行搜索或将其加入其他数据,那么这是有道理的。但是,文件数据(二进制或无二进制)通常不会以这种方式使用。
示例实施:
有更好的方法来分发文件数据,而不是将其输入到数据库中,例如分布式文件系统(检查GlusterFS,MooseFS,这两种方法只需添加额外的硬盘即可扩展,而MySQL则不会。) / p>
通常,我会使用数据的SHA1哈希值将文件数据存储在文件系统中作为文件的名称。如果哈希是98a75af529f07b1ef7be7400f51344b9f07b1ef7,那么我将它存储在这个目录结构中:
./98/a7/98a75af529f07b1ef7be7400f51344b9f07b1ef7
即,由前两个字符组成的顶级目录,由后两个字符组成的二级目录,最后是名称为总字符串的文件。通过这种方式,我可以拥有数十亿个文件而不会在一个目录中有这么多的文件,系统运行速度太慢。
然后我创建一个包含这些列的数据库表来保存元数据:
当我需要分层目录结构时,我还会创建一个目录表并将dir_id添加到上面的列列表中。
如果我编辑./98/a7/98a75af529f07b1ef7be7400f51344b9f07b1ef7
表示的文件,我实际上并没有在磁盘上更改该文件,我创建了一个新文件(因为新的文件内容将由新的SHA1哈希表示),并创建files文件表中的一个新条目,其中prev_id等于我编辑的文件的file_id。换句话说,我现在有版本。
如果我需要以分布式方式提供,我设置MySQL复制,然后使用GlusterFS在多个服务器上复制文件系统。
答案 1 :(得分:2)
我不得不想知道为什么你甚至对数据库感到烦恼,当你在chunk,store,retrieve和reassemble上添加的层在一个明确定义的文件系统结构上也能正常工作时。 MySQL希望将所有数据放在单个卷上,因此不需要在任何时候添加另一个驱动器,并且大量二进制数据的复制将会像二进制文件一样缓慢日志将最终复制您需要存储的数据量。
最简单的方法往往是最好的方法。直接在文件系统中存储它可能是最好的方法。如果你需要保存存储在哪里的索引,也许你会使用像MySQL这样的数据库,但是有很多方法可以完成同样的任务。技术越低越好。例如,不排除SQLite因为嵌入式数据库在轻度读写加载下表现良好,并且在备份和恢复方面具有“仅仅是文件”的优势。
话虽这么说,你所做的事情听起来与LevelDB非常相似,所以在你采用你的方法之前,你必须看到它与那个品种的键值文档存储有很大的不同。
答案 2 :(得分:2)
我认为你会在我开始研究这个问题时找到相当多的辩论。我倾向于倾向于存储在文件系统中并维护引用。但是,这并不是说从来没有时间将二进制数据存储在数据库中。
我想说,只是为了保持同步,本身并不是为了在数据库中存储二进制数据的论据。当然有办法使文件系统保持同步,以便数据库保持同步,文件系统也是如此。
最重要的是,关于这个话题存在相当多的争论,你必须选择适合你的方法。如果你设置了什么工作。用它。进行性能和负载测试以确保其正常工作。如果它没有阻止,请更改它。