apicloud apicloud

注册
查看: 3124|回复: 5

[APP开发技巧] 数据云Class设计上的一些取舍

主题:
7
帖子:
1577
云币:
1578

[APP开发技巧] 数据云Class设计上的一些取舍

3124 5 | 发表于 2015-7-22 15:56:29 |阅读模式 | |
本帖最后由 数据云咨询-北 于 2015-8-6 10:13 编辑

1.范式化与反范式化?

在项目设计阶段,明确集合的用途是对性能调优非常重要的一步。
从性能优化的角度来看,集合的设计我们需要考虑的是集合中数据的常用操作,例如我们需要设计一个日志(log)集合,日志的查看频率不高,但写入频率却很高,那么我们就可以得到这个集合中常用的操作是更新(增删改)。如果我们要保存的是城市列表呢?显而易见,这个集合是一个查看频率很高,但写入频率很低的集合,那么常用的操作就是查询。
对于频繁更新和频繁查询的集合,我们最需要关注的重点是他们的范式化程度,在上篇范式化与反范式化的介绍中我们了解到,范式化与反范式化的合理运用对于性能的提高至关重要。然而这种设计的使用非常灵活,假设现在我们需要存储一篇图书及其作者,在MongoDB中的关联就可以体现为以下几种形式:

1.1 完全分离(范式化设计)

示例1:
{
    "_id" : ObjectId("5124b5d86041c7dca81917"),
    "title" : "如何使用MongoDB",
    "author" : [
        ObjectId("144b5d83041c7dca84416"),
        ObjectId("144b5d83041c7dca84418"),
        ObjectId("144b5d83041c7dca84420"),     
    ]
}
我们将作者(comment) 的id数组作为一个字段添加到了图书中去。这样的设计方式是在非关系型数据库中常用的,也就是我们所说的范式化设计。在MongoDB中我们将与主键没有直接关系的图书单独提取到另一个集合,用存储主键的方式进行关联查询。当我们要查询文章和评论时需要先查询到所需的文章,再从文章中获取评论id,最后用获得的完整的文章及其评论。在这种情况下查询性能显然是不理想的。但当某位作者的信息需要修改时,范式化的维护优势就凸显出来了,我们无需考虑此作者关联的图书,直接进行修改此作者的字段即可。
1.2 完全内嵌(反范式化设计)
示例2:
{     
    "_id" : ObjectId("5124b5d86041c7dca81917"),      
    "title" : "如何使用MongoDB",
    "author" : [
        {
            "name" : "丁磊" ,
            "age" : 40,
            "nationality" : "china",
        },              
        {                       
            "name" : "马云",
            "age" : 49,         
            "nationality" : "china",
        },         
        {                  
            "name" : "张召忠",
            "age" : 59,     
            "nationality" : "china",  
        },   
    ]
}
在这个示例中我们将作者的字段完全嵌入到了图书中去,在查询的时候直接查询图书即可获得所对应作者的全部信息,但因一个作者可能有多本著作,当修改某位作者的信息时时,我们需要遍历所有图书以找到该作者,将其修改。
1.3 部分内嵌(折中方案)
示例3:
{
    "_id" : ObjectId("5124b5d86041c7dca81917"),
    "title" : "如何使用MongoDB",
    "author" : [
        {
            "_id" : ObjectId("144b5d83041c7dca84416"),
              "name" : "丁磊"
        },
        {
             "_id" : ObjectId("144b5d83041c7dca84418"),
             "name" : "马云"
        },
        {
             "_id" : ObjectId("144b5d83041c7dca84420"),
             "name" : "张召忠"
        },
    ]
}

这次我们将作者字段中的最常用的一部分提取出来。当我们只需要获得图书和作者名时,无需再次进入作者集合进行查询,仅在图书集合查询即可获得。
这种方式是一种相对折中的方式,既保证了查询效率,也保证的更新效率。但这样的方式显然要比前两种较难以掌握,难点在于需要与实际业务进行结合来寻找合适的提取字段。如同示例3所述,名字显然不是一个经常修改的字段,这样的字段如果提取出来是没问题的,但如果提取出来的字段是一个经常修改的字段(比如age)的话,我们依旧在更新这个字段时需要大范围的寻找并依此进行更新。
在上面三个示例中,第一个示例的更新效率是最高的,但查询效率是最低的,而第二个示例的查询效率最高,但更新效率最低。所以在实际的工作中我们需要根据自己实际的需要来设计表中的字段,以获得最高的效率。

想了解更多,推荐几篇文章你看下吧。
http://www.jianshu.com/p/bb0caddff60a
http://www.jianshu.com/p/21f5a73384d4
http://www.jianshu.com/p/f383059e6102

引用地址:http://www.codeceo.com/article/mongodb-performance.html


30分钟内迅速响应,一对一技术支持,每个问题均能获得专业解答----优先技术支持

业余车手

UID:22414

主题:
8
帖子:
815
云币:
12667

版主勋章APICloud粉丝

发表于 2015-7-22 19:39:54 |
感谢分享

主题:
7
帖子:
310
云币:
4018

中秋节APICloud粉丝女朋友单身狗

发表于 2015-7-23 08:38:07 |
感谢分享

新手上路

UID:123710

主题:
7
帖子:
41
云币:
337
发表于 2015-7-23 09:16:40 |
感谢分享。
作为外行人的理解,应该是要做到以下两点:
1. 读写分离,这样查询和更新可以针对不同的表进行操作
2. 要根据具体的业务进行适当的耦合,从而提高性能

驾校小白

UID:120116

主题:
0
帖子:
1
云币:
3
发表于 2015-8-6 19:53:25 |
感谢分享!!!!!!

业余车手

UID:22235

主题:
89
帖子:
1166
云币:
10256

版主勋章APICloud粉丝端午节

发表于 2015-8-20 10:55:54 |
没有最好的数据库设计,只有适合的数据库设计,学会取舍很关键。
您需要登录后才可以回帖 登录 | 立即注册

快速回复 返回顶部 返回列表