现今,最流行的数据模型莫过于关系模型。有基于此的关系型数据库主宰着大多数的企业数据存储。最初,SQL模型的提出就是旨在解决日常事务处理(例如记录销售流水)和批处理(例如货物计价)任务的。
NoSQL并不指向某种特定技术,它有时也被解释为“不只是SQL”(Not only SQL),它主要想解决的问题是:
- 比传统关系型数据库更大的吞吐量或者更灵活的可扩展性
- 某种特定的、在传统关系型数据模型中没有良好支持的查询操作
- 想要突破关系型数据库模式(schema)的限制,希望获得更灵活的数据展示
在现今的开发大环境下,面向对象已经成为大多数语言的特性,越来越多的设计模式和应用都依赖于这种特性。而在关系型数据库中,有时一行数据与应用代码中的类并没有办法完全适配。这无疑增大了开发成本。所以,好多主流编程语言都推出了对象-关系映射(ORM)来做数据与对象之间的转化。(例如Python中的SQLAlchemy)ORM在一定程度上缓解了传统关系型数据模型和面向对象之间的数据模型不匹配,但没有办法完全打通两种数据模型。
下面是拿LinkedIn中的个人信息做例子:
在传统关系型数据模型当中:个人档案可以当做是一行数据,user_id
作为全局唯一标识字段(主键),个人属性(例如姓名,性别等)都可以当做user
表一个字段。但是,大多数人都会有不止一段的教育经历、不止一份的工作经历,还有可能会有不止一个的认证证书。这就涉及到一对多的关系。关于这个一对多的关系,可以有以下几种存储方案:
-
按照传统数据模型的设计,这种一对多的关系应该将工作、教育、认证信息等单独存表,通过
外键约束user_id
外键约束和user
表关联;
-
在现有主流的关系型数据库中(MySQL, PostgreSql, Oracle, SQL Server等),增加了对于XML和json的支持,这样就可以将若干工作、教育、认证信息通过XML或者json的形式作为一个字段存储在表中;
-
对于相对老一点版本的数据库,可以把工作、教育、认证信息编码成xml或者json,当做字符串文本(text)存入数据库。相比第二种方法,它不支持对于该字段的搜索和查询;
对于上面这个例子而言,一个个人档案可以看作是一个自描述的类json文档。而文档型数据模型(例如MongoDB, RethinkDB,CouchDB)支持将这种模型存入数据库。
例如上面图中的信息,可以表示成下面的json文档:
{
"user_id": 251,
"first_name": "Bill",
"last_name": "Gates",
"summary": "Co-chair of the Bill & Melinda Gates... Active blogger.",
"region_id": "us:91",
"industry_id": 131,
"photo_url": "/p/7/000/253/05b/308dd6e.jpg",
"positions": [
{"job_title": "Co-chair", "organization": "Bill & Melinda Gates Foundation"},
{"job_title": "Co-founder, Chairman", "organization": "Microsoft"}
],
"education": [
{"school_name": "Harvard University", "start": 1973, "end": 1975},
{"school_name": "Lakeside School, Seattle", "start": null, "end": null}
],
"contact_info": {
"blog": "http://thegatesnotes.com",
"twitter": "http://twitter.com/BillGates"
}
}
以json对象存储可以从根本上避免数据存储模型与应用代码数据模型不匹配的问题,还可以提供丰富灵活的模式以供各种查询需求。
值得注意的是,对于industry_id, region_id等信息,user实体中都是存储相应信息的id。这是为了让用户输入信息时减少错误发生(如果输入纯文本,可能会有人输入“北京”,而有的人输入“北京市”,这种原因产生的错误应该尽量避免)。另外,相对固定的信息维护在一处也方便后续的添加修改。所以,在实际应用当中,对于相对固定的信息,应该另外存表,在主表存储id的方式进行信息关联。
这种场景又引发了数据多对一的情况。这种情况不是文档型数据库所擅长解决的领域(文档型数据库不支持join操作)。
不仅如此,考虑到各个用户之间可能会有推荐/认可(recommendation)的情况。这又引入来多对多的关系。
多对多
简单来说,如果你所面对的业务场景经常需要处理树形数据结构(也叫层级结构),或者一对多的结构,那么文档型数据模型应该会非常合适,而关系型数据库在这种场景下常常需要将数据拆到若干表中,带来许多额外查询开销和额外的应用代码处理关系映射。
而当你需要常常处理多对多关系时,文档型数据库缺乏相关支持,而关系型数据库也需要不少应用代码处理和一些额外数据库关联查询,这种场景下,图数据库也许是最好选择(例如neo4j)。
网友评论