最近,我们对数据库支持进行了很多思考,甚至主持了关于不和谐的社区讨论。目前,我们只有牛仔,但是我们最受欢迎的路线图项目正在增加对其他数据库的支持。从NOSQL思维过渡到SQL心态确实焦点了具体的差异。
如果您曾经想知道NOSQL的良好状况,另外,为什么SQL可能更适合某些应用程序,并且您厌倦了Tech Twitter告诉您该想什么,然后继续阅读以获取真实的信息 - 世界比较。
在这篇文章中,我将涵盖从NOSQL到SQL的调整功能和功能时,我们将面临的重大挑战,一路上,我将重点介绍每个范式的优点和缺点一些客观的影响。
数据定义语言
由于我们目前仅在MongoDB上,因此当您在有效负载配置中添加新字段时,我们不需要手动做一些事情喜欢添加新的表列。但是有了SQL,我们需要考虑一下(并使其无痛)。
ddl或Data Definition Language是SQL数据库定义和保持其结构的方式。即使您使用诸如Prisma之类的东西,它可以照顾很多头痛,您也需要对how Prisma migrations work非常熟悉。在那里,Prisma将自己的模式语法转化为SQL迁移。
不知道这意味着什么?继续前进,尝试简单地按照“在表中创建列”示例。如果您知道SQL,并且这对您来说并不新鲜,那么您可能会同意。但是这里有工作。
当您决定要在诸如MongoDB这样的NOSQL数据库中存储新字段时,您实际上不需要做除了开始存储数据。没有迁移,没有生成的DDL,没有模式 /数据库“同步”。< / p>
这显然是NOSQL的巨大胜利,但这也意味着NOSQL结构更加松散,可能导致错误。许多开发人员(更不用说项目要求)直接需要SQL的结构限制,并且允许将任何类型的数据存储在NOSQL文档中,可以从数据完整性方面呈现问题。因此,这两种方法肯定有利弊。
迁移
有趣的是,另一个非常热烈的有效负载功能是处理迁移的第一方方法。那让我们思考。显然,当您查看上面的Prisma迁移资源时,它们正在使用“迁移”一词来描述您的数据库形状从A到B的“迁移”。这是“迁移”的预期和最广泛使用的含义。<<<<<<<<<<<<<<< /p>
,但是我们在MongoDB上,但这不适用。但是开发人员仍在要求迁移支持。我想在这里做出一个具体的区别。在许多不同情况下,迁移可能意味着许多事情。
更改数据库形状
通常,它们被称为简单地修改您的数据库结构(DDL)。这通常是SQL的要求。例如,将列添加到表中是需要在某个时候运行的手动ALTER
。
转换现有数据
但故事有完全不同的一面。如果您需要更改或更改现有数据怎么办?如果您有一个full_name字段,并且需要将其分为两个单独的字段,即first_name和last_name怎么办?这样的东西非常普遍,需要手动,程序化管理。每当任何人都要求有效载荷以寻求迁移支持时,这就是他们的意思。
由于“迁移”的第二个方面,这意味着该概念与NOSQL和SQL数据库都相关。诸如Laravel之类的应用程序框架很好地处理了这一点,并具有完整的,真实的“迁移”工作流程,使您可以根据数据库交易来处理同一范式内的DDL和基于数据的转换。我个人认为,这是迄今为止解决此问题的最佳方法,这是ORM的一个经常被忽视的方面。有些ORM具有出色的编程迁移支持,而另一些ORMS仅处理生成的SQL中的DDL侧(屁股侧的疼痛)。请原谅我的法语,但我在这里被Mongodb宠坏了,我故意宠坏了自己。
如果您最终听我们的社区计划电话,您会发现我们在该电话会议上涵盖了我们的目标和未来愿景。我们希望通过不输出RAW SQL来在Laravel的一致性(解决两者的方法)之后对自己进行建模,而是输出ts文件,从而为您提供粒状,功能控制。
关系数据和绩效
在工程师心目中,SQL最大的胜利之一是其结构性的关系建筑。毫无疑问,人际关系是SQL的一流公民。大部分查询语言本身专门致力于结合和关联单独表的数据。
但是当然可以在NOSQL完成关系,那么该怎么办?实际差异是什么?
首先,SQL内有一系列功能,实际上可以实现关系数据完整性。在MongoDB中,这些类型的约束都需要手动编写,您最终需要“拥有”数据的完整性。在NOSQL中,您可能与另一个文档有关系。您可以删除该文档,但是除非您自己处理此文档,否则原始关系将仍然存在,但完全无效。那不是理想的,这给您带来了更多的工作。
让我们以有效负载为例。惊喜,惊喜。我们有一个relationship field,它可以将ID存储到其他相关文档中,这些文档是在您从数据库中检索文档时无缝合并的。我们利用dataloader pattern将给定查询所需的所有“人群”批量批量,使它们都非常快,并且尽可能少的单独查询到DB。
实际上,我们甚至比基于SQL的框架都大大胜过。在纯粹的关系测试中,we were 3x faster than Directus and 7x faster than Strapi在两者都在运行邮政编码时,我们在MongoDB上。
在不知道这两个平台的引擎盖下方的情况下,我在这里的收获是NOSQL和SQL之间的关系是可能的。如果您故意在表之间写出非常具体的连接的查询,并具有定义查询的能力,以便对单个查询进行与动态群体进行单个查询,那么SQL可能会在关系性能方面超出MongoDB。但是 - 您的应用程序逻辑将确定哪个速度更快,并且在任一方面很容易弄错。
这里要注意的一件事是,如果您使用的是GraphQl API或任何类型的动态 /表达查询语言,则不可能进行单个查询来返回所有填充的“关系” < / em>。这是因为它取决于查询的形状,以确定要“填充”的内容。这被称为n+1问题。您首先需要加载主文档,只有这样,您才能确定加载什么之后。如果这适用于您,那么SQL的大多数关系性能提高。
处理复杂的数据结构
NOSQL对SQL的绝对巨大胜利是您可以将复杂的数据直接存储在单个文档中。当您从数据库中读取它时,它可以与您想要的形状相同。一些SQL数据库(例如PostGres)通过JSON列具有非常出色的JSON支持,但是如果您在SQL数据库中过度使用JSON列,则首先不会利用SQL的优势,而且也可能会选择NOSQL。
那么,将复杂的数据结构存储在SQL中,而不会失去SQL的好处是什么样的?例如,以有效载荷的Group field:
为例
{
"id": "some-id-here",
"myGroup": {
"mySubField": "hello",
"anotherSubField": "goodbye"
}
}
上面的字段可以直接存储在nosql as-is中,这很棒。但是,基于SQL的数据库呢?我们是否使用双重下划线将嵌套体系结构转换为扁平的列结构?
id | myGroup__mysubfield | myGroup__anothersubfield |
---|---|---|
some-id-here |
hello |
goodbye |
这可以在功能上执行相同的操作,但是我们需要以某种方式“转换”其从数据库出发到其预期形状的数据。可行,但不那么优雅。
另外,我们可以“加入”另一个表,其中包含表示组中属性的列。这将变得越来越少,因为我们现在正在进行我们在NOSQL Land中不需要的加入。
最后,我们只是说“拧紧”,然后将组及其所有属性嵌入到一个JSON列中?
?基于现场的本地化
我们支持的一个特定功能,在NOSQL中很简单,但是SQL中更困难的是基于字段的本地化。您可能有30个环境,任何给定的文本字段都需要翻译成30个语言环境。
{
"id": "some-id-here",
"myLocalizedField": {
"en": "hello",
"es": "hola",
"de": "hallo"
}
}
再次,在Mongodb中,这是一个蛋糕。将整个位置存储在父文档上非常好,因为它们从根本上是该家长文档的一部分。
但是在SQL中,我们必须再次变得狡猾。您可能有30个或更多地点。这是否意味着每个文本字段的30列,全部在一个数据库中?
id | mylepalized field__es th> | mylepalized field__es | mylepalized field__dee th> |
---|---|---|---|
some-id-here |
hello |
hola |
hallo |
如果SQL中的列太多,您将开始看到性能的影响。但这需要以一种或另一种方式解决。同样,在这里,我们可以跳到JSON列,但后来我们输了很多。
基于阵列的结构
在NOSQL中,存储阵列很简单。只需将其保存在文档中并继续。
{
"id": "some-id-here",
"myArray": [
{
"subField": "hello"
},
{
"subField": "goodbye"
}
]
}
在SQL中处理基于数组的数据的良好认可和正确的方法就是为每个基于数组的字段创建一个新表(例如有效载荷的Arrays和Blocks字段)。然后,当您检索记录后,您只需加入每行数组数据即可。当然,这更复杂,我们在这里失去了一些表现,因为我们必须加入。但这是合乎逻辑的,至少答案比最近的几个示例更清晰。
要点
最终,我认为在阅读Tech Twitter或Reddit的任何内容时都会有健康的怀疑态度,告诉您作为工程师的好处。事实是,在某些情况下,SQL会为您表现更好,而NOSQL将在其他地方更合适。但这取决于您自己的独特要求。
总的来说,我认为可以肯定地说,如果您:
,SQL将为您的项目获胜。- 事先了解数据的形状
- 有信心您的模式不会经常更改或很乐意处理大量DDL迁移
- 具有相对“平坦”而不是复杂的模式
- 需要大量的关系结构
在另一面上,如果您:
,nosql将获胜- 经常管理复杂的,嵌套的数据结构,例如组,数组,块,局部字段数据和类似的
- 仅适用于类别,标签,作者等的简单结构,等等
- 想要避免完全处理DDL的东西并使您的生活更轻松
- 可以自己手动执行数据完整性和处理边缘案例,或者正在使用在NOSQL上为您处理这些东西的框架
啊,生活。一切都是妥协。尽管我想努力宣布胜利者,但我完全理解为什么要要求有效载荷SQL支持,尽管我个人认为MongoDB仍然更适合我们的大多数用户。最后,您可以选择适合您的任何东西。
计划会话记录
我们录制了上周举行的整个不和谐计划会议。要了解有关我们如何在有效载荷中接近未来SQL支持的更多信息,包括ORM评估等等,请聆听。
您在哪里可以帮忙?
首先,我们想收到您的来信!如果您还没有,请在我们的Roadmap GitHub Discussion上宣布自己的声音和投票。
从那里开始,一旦建立了未来的数据库适配器模式,任何人都可以构建适配器。我们很想看到一些社区生成的数据库和ORM支持,这只会加快我们正在构建的速度。< / p>
我们非常感谢我们在这个电话中看到的参与度,并且对将来做更多的事情感到非常兴奋。下一个可能是关于更换WebPack的,但是我们会看到的。 Follow us on Twitter要保持在循环或join our Discord中,以密切关注那里的对话。