在数据库中存储平台配置好还是存储在文件中更好?

49

我们目前正在开发一个应用程序,其中使用数据库表来存储平台设置,例如最大文件大小、最大用户数、支持的电子邮件等。

这意味着每次添加平台设置时,我们都必须向该表中添加一列。

在我以前的项目中,我习惯于将此类信息存储在文件中。

哪种方式更好/更快?

附注:我几乎可以确定有人已经有了这样的问题,但我似乎找不到它


4
如果您需要在存储的任何数据类型出现新类型时添加新列,则您的模式可能没有规范化。 - EricSchaefer
7个回答

67
我们将配置设置存储在一个键/值类型的表中,类似于:
CREATE TABLE Configuration.GlobalSettings
(
    SectionName VARCHAR(50),
    SettingName VARCHAR(50),
    SettingValue VARCHAR(1000),
    SettingType TINYINT
);
SectionNameSettingName是主键,我们只是将它们拆分以便更轻松地查询部分内容,并允许单独加载部分内容到处理程序,而不必一次性加载整个内容。 SettingValue是一个字符串,而SettingType是一个鉴别器,告诉我们应该如何解释设置值(例如1 =字符串,2 =布尔型,3 =十进制等)。

这意味着您不必为新的设置更改表结构,只需在部署脚本或设置这些内容的任何地方添加一个新的设置即可。

我们认为这种方式比文件更好,因为这意味着可以在需要时通过管理界面轻松编程更改配置值,这可以强制执行可以输入每个设置的逻辑。您无法像使用文件那样轻松地执行此操作(当然,这是可能的)。


2
你好,我知道这是一个非常古老的帖子,但为什么在将配置保存到文件时更改配置值不容易呢?通过 Properties/Preferences 实际上很容易做到,或者我有什么遗漏吗? - wederer
3
如果您只有一两台服务器,使用属性文件是很好的选择 - 但如果您要在数十个服务器上部署,则不那么方便了... - Greg Beech
现在不是使用NoSQL键/值存储更好地存储这些设置的方法吗? - Narendra Pathai
3
是的。在过去的五年里,世界发生了很大的变化。 - Greg Beech
1
Postgres使用HSTORE或JSONB可能比NoSQL更适合您的应用程序。 - Gringo Suave
我建议将第一列命名为“SettingSection”,这样我们就有了相同的前缀,更容易“记住”(即忘记)。 - Wolf

40

作为管理多个站点的特别大型应用程序的负责人,我可以告诉您,在本地文件中保存配置是非常麻烦的。通常情况下,配置被读取并缓存,并且无法在运行时更改,其他系统需要扩展规模,在这些系统中,配置需要重复更改和弹跳。

如果设计人员将系统属性保留在数据库中,那么在系统架构实施期间,我的生活将会变得更轻松10%。


31
赞一个,因为这种方法提供的简易程度比例不会被夸大。 - Ryall

25

这取决于您的应用程序。

将设置存储在数据库中有几个优点:

  1. 安全性 - 用户可以轻松地更改文件中的设置或覆盖其内容。
  2. 分发 - 可以更新相同的设置并加载到网络上的任何计算机上。

缺点:

  1. 依赖于数据库连接
  2. 从数据库读取时会产生开销。

将设置存储在文件中的优点:

  1. 快速简单易读且易修改。

缺点:

  1. 如上所述,存在安全问题。
  2. 可能需要对敏感数据进行加密。
  3. 版本控制很难,因为您必须为不同版本创建单独的文件。

这意味着每次添加平台设置都必须向该表添加一列 - 具体取决于您使用的数据库,但您可以将整个设置存储为XML(SQL Server允许此操作),以便在表中不需要更改架构来添加某项设置;您需要做的就是修改XML,向其中添加元素或从其中删除元素。

但最终,您必须自己决定,因为并没有对所有人都是更好或更糟的方法。


29
我认为这里的信噪比非常低。许多观点根本没有意义,比如“从数据库读取时的开销”。什么样的开销?几毫秒吗?只需一次读取配置信息即可解决问题。还有,“依赖于数据库连接”。应用程序的其余部分也是如此。然后你在说把XML“文件”存储在数据库中?有什么优势?而且文件版本控制很容易,任何版本控制系统都可以做到。数据库版本控制是一个更难的问题。 - Mark Bolusmjak
5
抱歉,让我澄清一下:
  1. 应用程序不必依赖于任何数据库连接,这只是问题中提到的一个选项。
  2. XML允许层次结构信息被封装,而不仅仅是扁平的键值对表格。
  3. 版本控制 - 我想你是对的,易或难实际取决于你如何设置它,所以我同意你的看法。
  4. 额外开销 - 只读取配置一次,是的,我想是可以的,但有时您可能想要进行更新和重新加载来更新或获取更新后的配置;就像我说的,这取决于整个架构。
- K2so
我认为这个答案非常误导人。配置通常不应该放在数据库中。作为一名开发者/架构师,在各种公司环境和大型应用程序中编程已经18年了,我完全不同意这个答案。对于任何执行“重要任务”的应用程序,版本控制配置(以跟踪更改)都是必须的。请参见下面的我的答案。 - Stephane Gosselin
@JéQueue 这个问题有几种解决方案可以在运行时更改。(但你肯定不想每次使用配置时都查询数据库)。你可以将其存储在缓存中,并设置失效期。15分钟看起来很好。说每次更新配置需要15分钟的时间是可以接受的,我在许多地方都见过这种情况。另一个更有趣的解决方案是,在盒子上开放一个套接字,允许你建立连接并告诉它使其配置缓存失效,以便下次请求配置时重新拉取。 - Cruncher

15
为什么每次都需要新建一列呢?为什么不只创建2列:名称和值。
我们的做法是在文件中设置默认值,然后在需要时通过部署覆盖数据库中的默认值。
此外,在速度方面,我们会缓存配置(并具备触发重新加载的能力)。每次需要属性时重新读取配置没有意义。因此,就速度而言,这并不重要。只需执行一次即可。

最后一篇帖子是一个类似ini的配置,具有部分实现。 - wener
1
我知道这已经很老了,但我发现这真的很有帮助。我在问自己一个问题...如何通过GUI轻松地使管理员访问我的应用程序设置,而不编写仅包含可能不断更改的一行的表格?这是完美的答案,也有助于避免强制使用未使用设置的NULL列值。 - Allenph

8
公正地说,答案并不是那么明显。上面的答案似乎没有考虑到需要在不同环境(如:开发、测试、预发布、生产)部署应用程序的情况。它们也没有考虑配置版本控制的重要性,即知道谁在哪里何时更改了什么。所有现代框架都提供了一种获取特定环境合适配置的方法,通常是通过环境变量。每个环境都有自己的配置,考虑symfony布置其配置文件的方式:
your-project/
├─ app/
│  ├─ ...
│  └─ config/
│     ├─ config.yml
│     ├─ config_dev.yml
│     ├─ config_prod.yml
│     ├─ config_test.yml
│     ├─ parameters.yml
│     ├─ parameters.yml.dist
│     ├─ routing.yml
│     ├─ routing_dev.yml
│     └─ security.yml
├─ ...

出于这些原因,我非常偏爱在文件中进行配置。
以上是我的个人看法。

我在这个答案中没有看到任何关于使用数据库的优缺点,或者文件的利弊。它似乎只是涉及到使用文件的可行性,并宣称因为它是可行的,所以更好。难道我漏掉了什么吗? - Jim Cullen
@JimCullen - 或许我表述不够清晰,对于配置管理和在不同环境(如本地、开发、QA、阶段、生产)中拥有不同配置的能力,很多人更喜欢基于文件的配置。这也允许对配置进行版本控制,知道谁在哪里更改了什么。在企业环境中,数据库中的配置无法很好地扩展,并且责任感也会丧失。以上是我的个人意见。 - Stephane Gosselin
如果我们并不真正重视应用程序是否将部署在不同的环境中,会怎样呢?如果配置只是关于用户在表单上可以填写多少选项,那又会怎样呢? - Mehdi Fracso
2
@MehdiFracso - 你说得对,动态配置通常存储在数据库中。即使在这种情况下,也有一种解决方法可以提供更多的灵活性。在我目前维护的Laravel应用程序中,默认设置在yml文件中(对于每个环境都相同),并且可以通过UI表单进行覆盖,其值保存在DB中并覆盖默认设置。这允许在配置文件中设置变量,甚至在部署时通过ENV变量设置它们,如果需要,最终用户可以通过UI进行覆盖。 - Stephane Gosselin
我希望我可以再给这个答案点赞一百次。通过构建和部署自动化,就更没有理由将设置保留在(定制的)数据库中,因为它们可以轻松地由相应的服务器进行管理。而这些服务器,最终往往使用配置文件。当Octo完全能够自行管理设置时,我不想配置Octo从某个人发明的表中加载设置。 - Yuck

2

我认为像其他人所说的那样,这取决于你的应用环境和需求。但是如果我不得不选择一个通用规则,我会说两者都需要。 首先,你需要创建一个数据库表来存储所有的配置信息。这有两个好处: 1)版本控制 - 允许您轻松跟踪以前的配置。 2)管理 - 您可以创建一个接口,让用户访问并更改设置。

其次,在将网站发布到生产环境中后,您需要创建一个文件来保存所有这些设置,以便轻松访问。实际上,如果您正在使用PHP进行网络编程,那么该文件应该是一个包含数组数据(键值对)的php文件,无需进一步操作即可使用。也就是说,如果您需要的最终输出是yaml或json格式的数组,那么就不需要将它们转换成数组。


0

就像其他人所说的,这取决于情况。需要问的问题是:设置需要多经常更改?如果需要更改,是否意味着正在进行更大的更改,或者已经存在接受不同值的功能?最重要的是...你的部署过程是什么?如果您有自动化部署流程,并且预测值更改的频率为每周或更长时间,我通常会使用设置文件。

为什么?版本控制和环境推广。使得在这里轻松切换这个和那个的确方便,但几乎不可能说“我的开发环境稳定并按预期工作,让我们将更改推广到下一个环境。”为什么?因为上周五未知的验收测试人员将enableSuperDuperFeatureEveryoneExpects切换为false。现在有解决这个问题的方法,在具有5个配置和1个开发人员的小型应用程序中,这不是问题,但是如果您正在处理具有8个团队,超过40个模式的100个配置表的企业应用程序,则拥有永无止境的噩梦。这可以通过配置模式来解决...但我个人会尽量在数据库中保留尽可能少的配置,除非您的应用程序很小...而定义“小”我会说,一旦有多个团队在应用程序上工作,您的应用程序就不再是小型的。

数据库配置的另一个问题是防止在运行时输入无效条目。如果您的应用程序有一个配置,比如defaultLandingPageAfterAuth,只接受home和dashboard这两个值,而某人在周五下午不小心将homw放入生产环境中,会发生什么?现在,您可以使用数据库枚举...我建议这样做...但您会吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接