【发布时间】:2011-01-10 00:18:28
【问题描述】:
如果我有一个由文件夹和文件组成的静态数据库,考虑到这将在 CGI 脚本中使用,访问和操作会比 SQL 服务器类型的数据库更快吗?
在处理文件和文件夹时,有哪些技巧可以提高性能?
【问题讨论】:
标签: sql performance cgi flat-file
如果我有一个由文件夹和文件组成的静态数据库,考虑到这将在 CGI 脚本中使用,访问和操作会比 SQL 服务器类型的数据库更快吗?
在处理文件和文件夹时,有哪些技巧可以提高性能?
【问题讨论】:
标签: sql performance cgi flat-file
我将添加到视情况而定的人群中。
这类问题没有通用答案,但在很大程度上取决于手头的情况。我什至最近将一些数据从 SQL 数据库移到了平面文件系统,因为数据库的开销,加上一些数据库连接可靠性问题,使得使用平面文件成为更好的选择。
在做出选择时我会问自己的一些问题包括:
我如何使用数据?例如,我会按照输入的顺序从头到尾读取行吗?还是我会搜索符合多个条件的行?
在一个程序执行期间我将多久访问一次数据?我会去一次以获取所有以塞林格为作者的书籍,还是会去几次以获取多个不同的作者?我会根据几个不同的标准去不止一次吗?
我将如何添加数据?我可以在末尾追加一行,这对于我的检索来说是完美的,还是需要使用它?
6 个月后代码看起来有多合乎逻辑? 我强调这一点是因为我认为这在设计事物时经常被遗忘(不仅仅是代码,这匹爱好马实际上来自我的时代作为一名海军机械师诅咒机械工程师)。在六个月内,当我必须维护您的代码(或者您在完成另一个项目之后)时,哪种存储和检索数据的方式会更有意义。如果从平面文件转换到数据库会导致 1% 的效率提升,但会增加一周的时间来弄清楚何时必须更新代码,那么你是否真的得到了改进。
【讨论】:
一般来说,数据库比文件慢。
如果您需要为文件编制索引,如果您正确执行,自定义索引结构上的硬编码访问路径总是有可能更快。
但在选择数据库而不是基于文件的解决方案时,“性能”并不是目标。
您应该问问自己,您的系统是否需要数据库提供的任何好处。如果是这样,那么小的性能开销是完全可以接受的。
所以:
基本上,问题在于哪个更容易开发。两者之间的性能差异不值得浪费开发时间。
【讨论】:
取决于您的信息是什么以及您的访问模式和规模是什么。关系数据库的两个最大好处是:
缓存。除非你很聪明,否则你写不出像数据库服务器一样好的缓存
优化器。
但是,对于某些专门的应用程序,与文件+文件夹数据存储相比,这两个好处都没有体现出来 - 因此答案是响亮的“取决于”。
至于文件/文件夹,技巧是:
【讨论】:
根据我的一点经验,与本地文件系统相比,基于服务器的数据库(即使是在本地机器上提供服务的数据库)往往具有非常慢的吞吐量。然而,这取决于一些事情,其中之一是渐近复杂性。将扫描大量文件列表与使用带有索引的数据库查找项目进行比较,数据库胜出。
我的一点经验是使用 PostgreSQL。我有一个包含 300 万行的表,而我只更新了 8,000 条记录。耗时 8 秒。
至于“过早的优化是万恶之源”这句话,我持保留态度。如果您使用数据库编写应用程序,然后发现它很慢,则可能需要大量时间才能切换到基于文件系统的方法或其他方法(例如 SQLite)。我会说你最好的选择是创建一个非常简单的工作负载原型,并使用这两种方法对其进行测试。我认为在这种情况下知道哪个更快是很重要的。
【讨论】:
正如其他人指出的那样:这取决于!
如果您真的需要找出哪个对您的目的性能更高,您可能需要生成一些示例数据以存储在每种格式中,然后运行一些基准测试。 Benchmark.pm 模块随 Perl 一起提供,并且可以很简单地与以下内容进行并排比较:
use Benchmark qw(:all) ;
my $count = 1000; # Some large-ish number of trials is recommended.
cmpthese($count, {
'File System' => sub { ...your filesystem code... },
'Database' => sub { ...your database code... }
});
您可以输入perldoc Benchmark 以获取更完整的文档。
【讨论】:
如果站点结构合适,在图像方面使用文件而不是数据库非常有用。创建代表匹配数据的文件夹并将图像放入其中。例如,您有一个文章站点,您将文章存储在 db 中。您不必将图像路径放在 db 上,使用 1、2、3 等主键命名文件夹并将图像放入其中。电子书、音乐文件、视频,这种方式可以用于所有媒体文件。如果您不搜索某些内容,则相同的逻辑适用于 xml 文件。
【讨论】:
这取决于数据的配置文件以及您将使用什么逻辑来访问它。如果您只需要保存和获取命名节点,那么基于文件系统的数据库可能会更快、更高效。 (为此,您还可以查看 Berkeley DB。)如果您需要进行基于索引的搜索,特别是如果您需要根据键连接不同的数据集,那么 SQL 数据库是您的最佳选择。
我会选择最适合您的应用程序的任何解决方案。
【讨论】:
正如其他人所说,这取决于:取决于数据的大小和性质以及您计划在其上运行的操作。
特别是对于 CGI 脚本,在每次页面查看时连接到数据库服务器都会导致性能下降。但是,如果您创建一个简单的基于文件的方法,则很容易产生更糟糕的性能问题;-)
除了 Berkeley DB File 解决方案,您还可以考虑使用 SQLite。这将为存储在本地文件中的数据库创建一个 SQL 接口。您可以使用 DBI 和 SQL 访问它,但没有服务器、配置或网络协议。如果将来需要数据库服务器,这可以更容易迁移(例如:如果您决定拥有多个前端服务器,但需要共享状态)。
在不了解任何细节的情况下,我建议使用 SQLite/DBI 解决方案,然后查看性能。这将通过相当简单的启动和良好的性能提供灵活性。
【讨论】:
要快速访问文件,取决于您正在做什么,mmap 非常方便。我刚刚在Effective Perl 博客中以Memory-map files instead of slurping them 的身份写过这个。
但是,我希望数据库服务器会快得多。当我们不知道您在做什么、您需要访问什么样的数据等等时,很难说什么对您来说更快。
【讨论】:
database certainly can be faster,
引用 SQLite 测试,
与使用 fread() 或 fwrite() 从磁盘上的单个文件读取或写入相同的 blob 相比,SQLite 读取和写入小 blob(例如缩略图)的速度快 35%¹。
此外,与将 Blob 存储在单个文件中相比,一个保存 10 KB Blob 的 SQLite 数据库使用的磁盘空间减少了约 20%。
出现性能差异(我们相信)是因为在 SQLite 数据库中工作时,open() 和 close() 系统调用仅调用一次,而在使用时为每个 blob 调用一次 open() 和 close()存储在单个文件中的 blob。看来调用 open() 和 close() 的开销大于使用数据库的开销。大小减小的原因是单个文件被填充到文件系统块大小的下一个倍数,而 blob 被更紧密地打包到 SQLite 数据库中。
本文中的测量是在 2017 年 6 月 5 日这一周使用 3.19.2 和 3.20.0 之间的 SQLite 版本进行的。您可能期望 SQLite 的未来版本会表现得更好。
【讨论】:
就像其他人所说的 DB 是一种工具,它会产生一些开销,但如果您的数据是静态的并且它是只读数据,从文件中读取目录会更快: 以下是我做过的一些测试: 我的文件名称为 .csv 在数据库中,我将列索引为“日期”,以便在数据库中找到相同的记录。每天有 30K-50K 记录/行和 100 列不同类型的数据(90% 浮动)。
数据库信息: PostgreSQL 11.5,16GB 内存
Table:
335,162,867 records
Table size: 110GB
Index size: 7GB
Total size: 117GB
Files:
Number of files: 8033
Total Files size: 158GB
Number of records/lines per file/date: 30K - 50K
不断地从文件中读取随机日期(1986-2019)的数据 比在 PostgreSQL 中读取同一日期的数据快 4-5 倍
【讨论】:
我为我的办公室管理站点(美国和巴西的 100 万员工)选择了文件/文件夹系统,这是我的第一个项目(作为工作)。
其实这是我从那以后做出的最不负责任但幸运的是最合适的决定。
为了处理这个文件系统,我还设置了一个 php 函数集以简化内容。我考虑使这些功能的事情是:
就是这样。
但在使用它时,我不得不考虑优化。例如,当谈到某人的最后一次见面时..
当某人 X 用户想要查看其他 Y 的 lastseen 时,我创建了一个名为 dataRequestingCluster 的文件夹,并在 X 下,其中包含 X 想要看到最后一次看到的所有内容(可能是 @ 987654327@ 的好友列表,如果 X 正在查看他的好友页面)并将该集群添加到 Y 的最后一次看到的表中(其中包含所有“Y 的最后一次看到的请求者单独的集群文件”并且每次更新 Y与服务器交互)
然后添加了一个机制,在 3 分钟内不使用时删除 dataRequestClusters(当 X 离开他的朋友页面时,无需为他更新最后一次看到)
我必须采用这种方法,因为更新 ALL_USERS 文件中最后一次看到的时间完全是个笑话。
最重要的是,这种方法比使用 MySql 的数据库系统要快得多……但是你必须动用大脑,多花 30% 的时间,但由此带来的快乐和完整性太棒了
这只是“最后一次见到”的一个案例
我多次使用不同的算法来解决每个问题,它总是比 sql/db 系统高效。
结论:文件系统使事情变得复杂,但它以令人震惊的方式提高质量的唯一方法......如果您不善于思考或时间较少或您不感兴趣你做什么你可能应该去 SQL/DB 系统。
6 个月后,我的服务器数据存储空间变成了 20GB(没有媒体文件..只是用户信息),但任何单个文件从未超过 200kb..它以最少的处理时间取得了惊人的成功。
【讨论】: