什么是Firebase Cloud Firestore中的非规范化?

Dav*_*ave 1 firebase google-cloud-firestore

在谈论Firebase Cloud Firestore时,这种非规范化到底意味着什么?我在互联网上阅读了几篇文章,并在此处找到了一些关于stackoverflow的答案,大多数答案都推荐这种方法。这种非规范化真正有什么帮助?总是有必要吗?

数据库扁平化和非规范化是一回事吗?

这是我的首要问题,希望我能找到一个可以帮助我理解这一概念的答案。我知道是不同的,但是我有两年的MySQL经验。

Ale*_*amo 9

什么是Firebase Cloud Firestore中的非规范化?

非规范化不仅与Cloud Firestore相关,而且是NoSQL数据库中通常使用的一种技术。

这种非正规化到底是什么?

非规范化是通过在数据库的其他不同位置添加冗余数据来优化NoSQL数据库性能的过程。正如@FrankvanPuffelen在他的评论中已经提到的,添加冗余数据是我的意思,它意味着我们复制一个地方或另一个地方已经存在的完全相同的数据,以适应否则可能无法实现的查询。因此,非规范化有助于掩盖关系数据库中固有的低效率。

这种非规范化真正有什么帮助?

是的,它确实。在涉及Firebase时,这也是一种非常普遍的做法,因为数据复制是更快读取数据的关键。我看到您是NoSQL数据库的新手,所以为了更好地理解,我建议您观看此视频,Denormalization在Firebase Database中是正常的。它用于Firebase实时数据库,但相同的原理也适用于Cloud Firestore。

总是有必要吗?

我们不只是为了使用非规范化而使用它。我们仅在绝对需要时才使用它。

数据库扁平化和非规范化是一回事吗?

让我们举个例子。假设我们有一个测验应用程序的数据库架构,如下所示:

Firestore-root
    |
    --- questions (collections)
          |
          --- questionId (document)
                 |
                 --- questionId: "LongQuestionIdOne"
                 |
                 --- title: "Question Title"
                 |
                 --- tags (collections)
                      |
                      --- tagIdOne (document)
                      |     |
                      |     --- tagId: "yR8iLzdBdylFkSzg1k4K"
                      |     |
                      |     --- tagName: "History"
                      |     |
                      |     --- //Other tag properties
                      |
                      --- tagIdTwo (document)
                            |
                            --- tagId: "tUjKPoq2dylFkSzg9cFg"
                            |
                            --- tagName: "Geography"
                            |
                            --- //Other tag properties
Run Code Online (Sandbox Code Playgroud)

我们可以通过简单地将tags集合移动到一个单独的顶级集合中来展平数据库,如下所示:

Firestore-root
    |
    --- questions (collections)
    |     |
    |     --- questionId (document)
    |            |
    |            --- questionId: "LongQuestionIdOne"
    |            |
    |            --- title: "Question Title"
    |
    --- tags (collections)
          |
          --- tagIdOne (document)
          |     |
          |     --- tagId: "yR8iLzdBdylFkSzg1k4K"
          |     |
          |     --- tagName: "History"
          |     |
          |     --- questionId: "LongQuestionIdOne"
          |     |
          |     --- //Other tag properties
          |
          --- tagIdTwo (document)
                |
                --- tagId: "tUjKPoq2dylFkSzg9cFg"
                |
                --- tagName: "Geography"
                |
                --- questionId: "LongQuestionIdTwo"
                |
                --- //Other tag properties
Run Code Online (Sandbox Code Playgroud)

现在,要获取与特定问题对应的所有标签,您只需查询属性包含所需问题ID 的tags集合questionId

或者,您可以在同一时间对数据库进行扁平化和非规范化,如以下模式所示:

Firestore-root
    |
    --- questions (collections)
    |     |
    |     --- questionId (document)
    |            |
    |            --- questionId: "LongQuestionIdOne"
    |            |
    |            --- title: "Question Title"
    |            |
    |            --- tags (collections)
    |                 |
    |                 --- tagIdOne (document) //<----------- Same tag id
    |                 |     |
    |                 |     --- tagId: "yR8iLzdBdylFkSzg1k4K"
    |                 |     |
    |                 |     --- tagName: "History"
    |                 |     |
    |                 |     --- //Other tag properties
    |                 |
    |                 --- tagIdTwo (document) //<----------- Same tag id
    |                       |
    |                       --- tagId: "tUjKPoq2dylFkSzg9cFg"
    |                       |
    |                       --- tagName: "Geography"
    |                       |
    |                       --- //Other tag properties
    |
    --- tags (collections)
          |
          --- tagIdOne (document) //<----------- Same tag id
          |     |
          |     --- tagId: "yR8iLzdBdylFkSzg1k4K"
          |     |
          |     --- tagName: "History"
          |     |
          |     --- questionId: "LongQuestionIdOne"
          |     |
          |     --- //Other tag properties
          |
          --- tagIdTwo (document) //<----------- Same tag id
                |
                --- tagId: "tUjKPoq2dylFkSzg9cFg"
                |
                --- tagName: "Geography"
                |
                --- questionId: "LongQuestionIdTwo"
                |
                --- //Other tag properties
Run Code Online (Sandbox Code Playgroud)

你看,标签的对象是相同的,以及在users -> uid -> tags -> tagIdtags -> tagId。因此,我们将数据展平以某种方式对现有数据进行分组。

有关更多信息,您还可以查看:

因为您说自己有SQL背景,所以请尝试考虑一种标准化设计,该设计通常将不同但相关的数据存储在单独的逻辑表中,这称为关系。如果这些关系在物理上存储为单独的磁盘文件,则完成从多个关系中抽取信息的查询(联接操作)可能会很慢。如果加入了许多关系,那可能会太慢了。因为在NoSQL数据库中,我们没有“ JOIN”子句,所以我们必须创建不同的解决方法来获得相同的行为。