热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SQLVSNoSQL如何选择数据库

在前一篇文章中我们主要的讨论了SQL与NoSQL数据库之间的主要的差别。接下来,我们将会利用上一篇中的知识来确定在特定的场景中如何确定比较好的选择。首先我们先来总结一下:SQL数据库:​使用表存储相关

在前一篇文章中我们主要的讨论了SQL与NoSQL数据库之间的主要的差别。接下来,我们将会利用上一篇中的知识来确定在特定的场景中如何确定比较好的选择。

首先我们先来总结一下:

SQL数据库:

  • ​使用表存储相关的数据

  • 在使用表之前需要先定义标的模式

  • 鼓励使用规范化来减少数据的冗余

  • 支持使用JOIN操作,使用一条SQL语句从多张表中取出相关的数据

  • 需要满足数据完整性约束规则

  • 使用事务来保证数据的一致性

  • 能够大规模的使用

  • 使用强大的SQL语言进行查询操作

  • 提供大量的支持,专业技能和辅助工具

NoSQL数据库:

  • 使用类JSON格式的文档来存储键值对信息

  • 存储数据不需要特定的模式

  • 使用非规范化的标准存储信息,以保证一个文档中包含一个条目的所有信息

  • 不需要使用JOIN操作

  • 允许数据不用通过验证就可以存储到任意的位置

  • 保证更新的单个文档,而不是多个文档

  • 提供卓越的性能和可扩展性

  • 使用JSON数据对象进行查询

  • 是一种新型的技术

SQL数据库适合那些需求确定和对数据完整性要去严格的项目。NoSQL数据库适用于那些对速度和可扩展性比较看重的那些不相关的,不确定和不断发展的需求。简单来说就是:

  • SQL是精确的。它最适合于具有精确标准的定义明确的项目。典型的使用场景是在线商店和银行系统。

  • NoSQL是多变的。它最适合于具有不确定需求的数据。典型的使用场景是社交网络,客户管理和网络分析系统。

很少有项目能够很好的适用于一种数据库。如果你对数据的需求比较小或是非标准化的数据任何一种数据库都是可以的。你比我更了解你的项目,我不建议你将SQL上的数据移植到NoSQL上反之亦然,除非它能够提供非常可观的收益。当然选择权在于你自己。在项目的一开始就要考虑好使用它们的利弊,这样才不会导致选择错误。

场景一:通讯记录

我们来重新的定义操作并基于SQL实现通讯录系统。我们初始简单的定义contact表拥有如下几个字段;

  • id

  • title

  • firstname

  • lastname

  • gender

  • telephone

  • email

  • address1

  • address2

  • address3

  • city

  • region

  • zipcode

  • country

问题一:很少有人只拥有一个手机号。或许我们可以再添加三个字段:固定电话,移动电话和工作电话,但是无论我们给一个联系人分配了多少个字段总会有人需要更多。我们需要创建一个单独的telephone表,这样就可以给一个联系人存多个号码了。这样也就规范化了我们的数据— 我们不需要一个没有电话的联系人:

  • contact_id

  • name (说明字段:固定,工作,私人等.)

  • number

问题二:对于联系人邮箱我们也会遇到上述问题,因此我们也需要创建一个email的表:

  • contact_id

  • name (说明字段:固定,工作,私人等.)

  • address

问题三:我们在填写联系人信息是我们并不希望填写他的地理位置,或者我们想记录他工作、生活、旅游的地方等。因此我们需要一个address表:

  • contact_id

  • name (text such as home, office, etc.)

  • address1

  • address2

  • address3

  • city

  • region

  • zipcode

  • country

我们原先设计的contact表就精简为:

  • id

  • title

  • firstname

  • lastname

  • gender

好了,我们已经设计了一个规范化的数据库,可以用来存储任何一个联系人的电话号码,邮箱地址和住址了。但是......

模式是固定不变的

我们并没有考虑到联系人的生日,公司或者职位。不管我们添加多少个字段,我们会得到更多的需求:备注,周年纪念日,关系,社交账号,喜欢巧克力的种类等等。预测每一个需求对于我们来说是非常困难的,因此我们需要创建一张表其中存储的形式是键值对来应对不断增加的需求。

数据是碎片化的

对于开发人员和系统管理员来说不断地检查数据库是比较麻烦的。程序的逻辑会变得更复杂效率更慢,因为使用一条select语句来JOIN多个表来取出一个联系人的全部信息不太实际。(当然这也是可以实现的,但是当一个联系人中国包含电话号码,邮件地址和住址信息时:如果一个人有3个电话号码,五个邮箱和两个住址,那么SQL查询会产生30个结果,也就是说说这样的效率会很慢。)

最后,全文搜索是非常困难的。如果一个人要查询一个字符型:favorite,我们需要依次查询上述的四张表判断是否是一个联系人的姓名,电话,邮件或者地址依据这些把结果进行排序。如果你使用过WordPress的搜索,你就会发现是都么的烦人了!

使用NoSQL来替代SQL

我们的联系人关注的是人这个实体。然而关于人的信息是不可预测的并且在不同的阶段的需求也会不一样。如果我们使用NoSQL数据库会比较方便,NoSQL将一个人的信息存储为一个文档并放入contacts的集合中: 

{
name: [
"Billy", "Bob", "Jones"
],
company:
"Fake Goods Corp",
jobtitle:
"Vice President of Data Management",
telephone: {
home:
"0123456789",
mobile:
"9876543210",
work:
"2244668800"
},
email: {
personal:
"bob@myhomeemail.net",
work:
"bob@myworkemail.com"
},
address: {
home: {
line1:
"10 Non-Existent Street",
city:
"Nowhere",
country:
"Australia"
}
},
birthdate: ISODate(
"1980-01-01T00:00:00.000Z"),
twitter:
'@bobsfakeaccount',
note:
"Don't trust this guy",
weight:
"200lb",
photo:
"52e86ad749e0b817d25c8892.jpg"
}

在这个示例中,我们没有存储这个人的性别和职衔,并且可以添加一些别的联系人没用的信息。在NoSQL中这样的存储是合法的,并且我们可以按照各人的意愿来添加和删除一个字段。

因为一个联系人存储在一个文档中,因此我们可以使用一个查询语句取出一个人的所有信息。对于全文搜索,在MongoDB中我们可以在contact的字段中定义一个索引:

db.contact.createIndex({ "$**": "text" });

然后我们就可以使用如下的语句进行全文搜索:

db.contact.find({
$
text: { $search: "something" }
});

 

场景二:社交网络

一个典型的社交网络使用的联系人的信息是相似,但是也会增加一些新的功能例如:社交网络,状态更新,私信和点赞。这些功能会根据用户的需求进行添加或者删除,预测用户的需求对开发人员来说是非常困难的。

另外:

  • 大多数的更新都有一个原始的出发点:用户。但是,对于开发人员来说一次性的把所有的回馈都进行更新是不可能的。

  • 不管用户怎么想,一个失败的版本并可能造成太大的经济损失。一个应用的接口设计和功能表现是比数据的完整性的优先级要高。

因此,NoSQL是一个不错的选择。数据库允许我们存储不同类型的数据以便于我们快速的开发出新的功能。例如,因为所有的数据状态的更新都可以在status的集合中的一个文档中进行:

 
{
user_id: ObjectID(
"65f82bda42e7b8c76f5c1969"),
update: [
{
date: ISODate(
"2015-09-18T10:02:47.620Z"),
text:
"feeling more positive today"
},
{
date: ISODate(
"2015-09-17T13:14:20.789Z"),
text:
"spending far too much time here"
}
{
date: ISODate(
"2015-09-17T12:33:02.132Z"),
text:
"considering my life choices"
}
]
}

 

尽管对于这个文档来说数据会变得多一些,但是我们可以仅仅取出文档的一个子集,例如:最新的状态等。对于每一个用户来说历史记录也会很容易搜索的到。

场景三:仓库管理系统

现在,我们来分析一下一个仓库的管理系统。我们需要记录如下的信息:

  • 货物入库的信息和存放的位置信息

  • 货物在仓库中的移动,例如:为相同的货物分配相邻的位置存放

  • 货物的摆放顺序以及配送货物之后的一系列问题。

数据需求:

  1. 保存货物的基本信息例如:尺寸、大小、颜色等,这些不相关的数据我们要能够用到任何的货物上。我们不可能去考虑一些货物个性化的信息例如:笔记本处理器的速度或者是一部手机电池的寿命。

  2. 我们要尽可能的避免错误的发生。我们不能让货物凭空消失或者将货物存放到已经存放货物的位置上去。

  3. 以更加简单的方式操作。我们记录将一件货物从一个位置移动到另一个位置或者从A移动到B的操作是相同的。

因此,我们需要考虑对数据的完整性和对于事务的支持。目前来说也就是SQL能够很好地满足我们的需求。

总结

我希望上述的案例能够对你有一定的帮助,但是每一个实际的项目都是不同的,对一无二的你需要自己去做决定选择一种适合的。(尽管,对于我们开发人员来说我们不太愿意去改变我们现有的选择,无论新的技术有多好!O(∩_∩)O)

建议:去尝试了解更多新的技术。这样我们就可以非常有理由的选择一种数据库进行开发。祝你好运!

 


推荐阅读
  • NoSQL数据库,即非关系型数据库,有时也被称作Not Only SQL,是一种区别于传统关系型数据库的管理系统。这类数据库设计用于处理大规模、高并发的数据存储与查询需求,特别适用于需要快速读写大量非结构化或半结构化数据的应用场景。NoSQL数据库通过牺牲部分一致性来换取更高的可扩展性和性能,支持分布式部署,能够有效应对互联网时代的海量数据挑战。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • Oracle字符集详解:图表解析与中文乱码解决方案
    本文详细解析了 Oracle 数据库中的字符集机制,通过图表展示了不同字符集之间的转换过程,并针对中文乱码问题提供了有效的解决方案。文章深入探讨了字符集配置、数据迁移和兼容性问题,为数据库管理员和开发人员提供了实用的参考和指导。 ... [详细]
  • 数据库多表联合查询:内连接与外连接详解
    在数据库的多表查询中,内连接和外连接是两种常用的技术手段。内连接用于检索多个表中相互匹配的记录,即只有当两个表中的记录满足特定的连接条件时,这些记录才会被包含在查询结果中。相比之下,外连接则不仅返回匹配的记录,还可以选择性地返回不匹配的记录,具体取决于左外连接、右外连接或全外连接的选择。本文将详细解析这两种连接方式的使用场景及其语法结构,帮助读者更好地理解和应用多表查询技术。 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • 本文深入探讨了 hCalendar 微格式在事件与时间、地点相关活动标记中的应用。作为微格式系列文章的第四篇,前文已分别介绍了 rel 属性用于定义链接关系、XFN 微格式增强链接的人际关系描述以及 hCard 微格式对个人和组织信息的描述。本次将重点解析 hCalendar 如何通过结构化数据标记,提高事件信息的可读性和互操作性。 ... [详细]
  • 公司计划部署邮件服务器,考虑到已有域名,决定自行搭建内部邮件服务器。经过综合考量,最终选择在Linux环境中进行搭建,并记录了相关配置和实践过程。本文将详细介绍Postfix的基本设置步骤和实践经验,帮助读者快速掌握邮件服务器的搭建方法。 ... [详细]
  • MongoDB高可用架构:深入解析Replica Set机制
    MongoDB的高可用架构主要依赖于其Replica Set机制。Replica Set通过多个mongod节点的协同工作,实现了数据的冗余存储和故障自动切换,确保了系统的高可用性和数据的一致性。本文将深入解析Replica Set的工作原理及其在实际应用中的配置和优化方法,帮助读者更好地理解和实施MongoDB的高可用架构。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • 在使用关系型数据库时,通常需要通过用户名和密码进行身份验证才能访问数据。然而,MongoDB默认情况下并不强制要求这种身份验证机制,使得用户无需凭据即可访问并执行各种操作。虽然这一设计简化了初学者的上手过程,但也带来了显著的安全风险。为了提升MongoDB的连接安全性,本文将探讨多种策略与实践,包括启用身份验证、配置网络访问控制、加密通信以及定期审计安全设置,以确保数据库的安全性和数据的完整性。 ... [详细]
  • Mongoose E11000 错误:集合中出现重复键问题分析与解决 ... [详细]
author-avatar
大女人小诺
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有