66

如果我有一个由文件夹和文件组成的静态数据库,考虑到这将在 CGI 脚本中使用,访问和操作会比 SQL 服务器类型的数据库更快吗?

处理文件和文件夹时,提高性能的技巧是什么?

4

13 回答 13

67

我将添加到这取决于人群。

这是一种没有通用答案但在很大程度上取决于手头情况的问题。我什至最近将一些数据从 SQL 数据库移动到平面文件系统,因为 DB 的开销,加上一些 DB 连接可靠性问题,使得使用平面文件成为更好的选择。

在做出选择时我会问自己的一些问题包括:

  1. 我如何使用数据?例如,我会按照输入的顺序从头到尾读取行吗?或者我会搜索匹配多个条件的行吗?

  2. 在一个程序执行期间,我将多久访问一次数据?我会去一次以获取所有以塞林格为作者的书籍,还是会去几次以获取多个不同的作者?我会根据几个不同的标准去不止一次吗?

  3. 我将如何添加数据?我可以只在末尾附加一行,这对于我的检索来说是完美的,还是需要使用它?

  4. 六个月后代码的逻辑性如何? 我强调这一点是因为我认为这在设计事物时经常被遗忘(不仅仅是代码,这匹爱好马实际上来自我作为海军机械师诅咒机械工程师的日子)。在六个月内,当我必须维护您的代码(或者您在完成另一个项目之后)时,哪种存储和检索数据的方式会更有意义。如果从平面文件到数据库会导致 1% 的效率提高,但在必须更新代码时增加一周的时间来解决问题,那么你真的改进了一些事情。

于 2010-01-27T15:45:28.553 回答
29

作为一般规则,数据库比文件慢。

如果您需要对文件进行索引,那么如果您正确执行,自定义索引结构上的硬编码访问路径将始终具有更快的潜力。

但是在选择数据库而不是基于文件的解决方案时,“性能”并不是目标。

您应该问问自己您的系统是否需要数据库提供的任何好处。如果是这样,那么小的性能开销是完全可以接受的。

所以:

  1. 您是否需要处理多个用户和并发更新?(嗯;你确实说过它是静态的。)
  2. 您是否需要灵活性以便从各种角度轻松查询数据?
  3. 您是否有多个用户,并且可以从利用现有的安全模型中获益?

基本上,问题是哪个更容易开发。两者之间的性能差异不值得浪费开发时间。

于 2010-01-27T15:24:52.453 回答
24

取决于您的信息是什么以及您的访问模式和规模是什么。关系数据库的两个最大好处是:

  1. 缓存。除非你很聪明,否则你写不出像数据库服务器一样好的缓存

  2. 优化器。

然而,对于某些专门的应用程序,与文件+文件夹数据存储相比,这两个好处都没有体现出来——因此答案是响亮的“取决于”。

至于文件/文件夹,技巧是:

  • 缓存频繁请求文件的内容
  • 有小目录(由于读取大目录的内容需要时间,因此访问深度嵌套的小目录中的文件比访问扁平结构中的文件要快得多)。
  • 还有其他更高级的优化(跨磁盘切片,放置在磁盘或不同分区的不同位置等) - 但如果您需要该级别,则最好首先使用数据库。
于 2010-01-27T15:18:15.713 回答
14

根据我的一点经验,与本地文件系统相比,基于服务器的数据库(即使是在本地机器上提供服务的数据库)往往具有非常慢的吞吐量。然而,这取决于一些事情,其中​​之一是渐近复杂性。将扫描大量文件列表与使用带有索引的数据库查找项目进行比较,数据库胜出。

我的一点经验是使用 PostgreSQL。我有一个包含 300 万行的表,而我只更新了 8,000 条记录。花了8秒。

至于“过早的优化是万恶之源”这句话,我会持保留态度。如果您使用数据库编写应用程序,然后发现它很慢,则可能需要大量时间才能切换到基于文件系统的方法或其他方法(例如 SQLite)。我想说你最好的选择是创建一个非常简单的工作负载原型,并使用这两种方法对其进行测试。我相信在这种情况下知道哪个更快是很重要的。

于 2010-02-01T04:23:55.577 回答
7

正如其他人指出的那样:这取决于!

如果您确实需要找出哪个对您的目的性能更高,您可能需要生成一些示例数据以存储在每种格式中,然后运行一些基准测试。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以获取更完整的文档。

于 2010-01-27T15:29:50.020 回答
4

如果站点结构合适,在图像方面使用文件而不是 db 非常有用。创建代表匹配数据的文件夹并将图像放入其中。例如,您有一个文章站点,您将文章存储在 db 中。您不必将图像路径放在 db 上,使用主键(如 1、2、3..)命名文件夹并将图像放入其中。电子书、音乐文件、视频,所有媒体文件都可以采用这种方式。如果您不搜索某些内容,则相同的逻辑适用于 xml 文件。

于 2013-11-28T09:21:11.110 回答
2

这取决于数据的配置文件以及您将使用什么逻辑来访问它。如果您只需要保存和获取命名节点,那么基于文件系统的数据库可能会更快、更高效。(为此,您还可以查看 Berkeley DB。)如果您需要进行基于索引的搜索,特别是如果您需要根据键连接不同的数据集,那么 SQL 数据库是您的最佳选择。

我会选择最适合您的应用程序的任何解决方案。

于 2010-01-27T15:20:16.350 回答
2

正如其他人所说,这取决于:数据的大小和性质以及您计划在其上运行的操作。

特别是对于CGI 脚本,在每个页面视图上连接到数据库服务器都会导致性能下降。但是,如果您创建一个简单的基于文件的方法,则很容易产生更糟糕的性能问题;-)

除了 Berkeley DB File 解决方案,您还可以考虑使用SQLite。这将为存储在本地文件中的数据库创建一个 SQL 接口。您可以使用 DBI 和 SQL 访问它,但没有服务器、配置或网络协议。如果将来需要数据库服务器,这可以更容易迁移(例如:如果您决定拥有多个前端服务器,但需要共享状态)。

在不知道任何细节的情况下,我建议使用 SQLite/DBI 解决方案,然后查看性能。这将通过相当简单的启动和良好的性能提供灵活性。

于 2010-01-27T15:38:21.050 回答
2

要快速访问文件,取决于您正在做什么,mmap 非常方便。我刚刚在Effective Perl博客中将其作为Memory-map 文件而不是 slurping 来写。

但是,我希望数据库服务器会快得多。当我们不知道你在做什么、你需要访问什么样的数据等等时,很难说什么对你来说更快。

于 2010-02-01T04:13:16.023 回答
2

就像其他人说的一样,数据库是一个工具,它会产生一些开销,但是如果您的数据是静态的并且它是只读数据,从文件中读取目录会更快:这是我做过的一些测试:我有文件文件的名称为 .csv 在数据库中,我将列索引为“日期”,以便在数据库中找到相同的记录。每天有 30K-50K 记录/行和 100 列不同类型的数据(90% 浮动)。

数据库信息:PostgreSQL 11.5,16GB RAM

  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 倍

于 2019-03-17T11:31:01.623 回答
2

数据库当然可以更快

引用 SQLite 测试,

SQLite 读取和写入小 blob(例如,缩略图)比使用 fread() 或 fwrite() 从磁盘上的单个文件读取或写入相同的 blob 快 35%¹。

此外,与将 Blob 存储在单个文件中相比,一个保存 10 KB Blob 的 SQLite 数据库使用的磁盘空间减少了约 20%。

出现性能差异(我们相信)是因为在 SQLite 数据库中工作时,open() 和 close() 系统调用仅调用一次,而当使用存储在个别文件。看起来调用 open() 和 close() 的开销大于使用数据库的开销。大小减少的原因是单个文件被填充到文件系统块大小的下一个倍数,而 blob 被更紧密地打包到 SQLite 数据库中。

本文中的测量是在 2017-06-05 的一周内使用 3.19.2 和 3.20.0 之间的 SQLite 版本进行的。您可能期望 SQLite 的未来版本会表现得更好。

于 2020-07-13T12:49:46.820 回答
1

我会给你和其他人一样的答案, 这取决于

在单个服务器返回数据(只读)的简单场景中,Yes 文件系统将非常好并且易​​于管理。

但是,当您拥有多个服务器时,您将不得不管理分布式文件系统,如glusterfsceph等。

数据库是为您管理所有这些的工具,分布式文件系统、压缩、读/写、锁等。

希望这会有所帮助。

于 2018-03-26T17:01:35.583 回答
1

我为我的办公室管理站点(美国和巴西的 100 万员工)选择了文件/文件夹系统,这是我的第一个项目(作为工作)。

事实上,这是我从那以后做出的最不负责任但幸运的是最合适的决定。

为了处理这个文件系统,我还设置了一个 php 函数集以简化内容。我考虑使这些功能的事情是:

  • 创建表格文件(如 csv)
  • 创建包含这些文件的文件夹,
  • 让对选定文件中的每一行重复一个函数,
  • 让更改/删除选定文件中选定的列/行数据迭代
  • 并将二进制文件保存为单独的文件

就这样。

但是在使用它时,我不得不考虑优化这么多。例如,当谈到最后一次见到某人时..

当某个X用户想要查看lastseen其他用户时,Y我创建了一个名为的文件夹,在该文件夹dataRequestingClusterX包含X想要查看最后一次看到的所有内容(X如果X正在查看他的朋友页面,则可能是 的好友列表)并将该集群添加到Y的最后一次看到的表中(其中包含所有 "Y的最后一次出现的请求者单独的 clusterFiles" 并在每次 Y 与服务器交互时更新)

然后添加了一个机制,在 3 分钟内不使用时删除 dataRequestClusters(当 X 离开他的朋友页面时,不需要为他更新最后一次看到的)

我必须遵循这种方法,因为更新最后一次出现在 ALL_USERS 文件中是一个完全的笑话。

最重要的是,这种方法比使用 MySql 的数据库系统要快得多……但是你必须动用大脑和多 30% 的时间,但由此带来的快乐和完整性真是太棒了

这只是“最后一次见到”的一个案例

很多次我使用不同的算法来解决每个问题,它总是比 sql/db 系统高效。

结论:文件系统使事情变得复杂,但它以令人震惊的方式提高质量的唯一方法......如果您不善于思考或时间较少,或者您对自己所做的事情不感兴趣,您可能应该使用 SQL/DB系统。

6 个月后,我的服务器数据存储空间变成了 20GB(没有媒体文件.. 只是用户信息),但任何单个文件从未超过 200kb.. 它以最少的处理时间取得了惊人的成功。

于 2020-07-13T11:13:00.827 回答