关于SQL数据库和NoSql数据库的数据库选择案例

时间:2022-11-28 08:51:37
一、SQL和NoSQL数据库的特点对比
SQL 数据库的特点:
在表中存储相关联的数据
在使用之前需要定义表的一个模式
鼓励标准化减少数据冗余
支持从多个表中检索相关数据表连接在一个单一的命令
实现数据完整性规则
提供事务使两个或两个以上的成功或失败的数据更改作为一个原子单元
可以扩展(有一些努力)
使用一个强声明性语言查询
提供足够的支持,专业技能和工具。

NoSQL 数据库的特点:
将相关联的数据存储在类似 JSON 格式,名称-值
可以保存没有指定格式的数据
通常必须规范化,所以一个项目的信息包含在一个文档里
应该不需要连接(假设使用规范化的文档)
允许任何数据被保存在任何时候任何地方,不需要验证
保证更新一个文档 - 但不是多个文档
提供出色的性能和可伸缩性
使用 JSON 数据对象查询
是一个新的、令人兴奋的技术。
SQL 数据库是一个理想的项目,确定好了需求和健壮的数据的完整性是至关重要的。NoSQL 数据库是无关理想,不确定的或者不断变化的数据需求 ,在速度和可伸缩性上更重要。 
简单的术语:
SQL 是数字。它最适合明确的定义,精确规范的独立项目。典型的使用案例是在线商城和银行系统。
NoSQL 是模拟。它最适合无固定要求的组织数据。典型的使用案例是社交网络,客户管理和网络分析系统。

二、场景案例
场景一:一个联系人列表
让我们重新发明*,实现一个基于sql的通讯录系统。我们最初接触表的时候,天真的定义以下字段:
id (主键ID)
title (标题)
firstname (姓)
lastname (名)
gender (性别)
telephone (电话)
email   (邮箱)
address1 (地址1)
address2 (地址2)
address3 (地址3)
city       (城市)
region    (区/县)
zipcode    (邮政编码)
country    (国家)
问题一: 很少人只有一个电话号码。我们可能需要至少三个号码:一个座机,一个移动电话,一个工作电话。但是有多少个号码无关紧要——有些人、有些地方需要更多。让我们创建一个单独的 telephone 表,这样的话他们想要多少联系人都可以。这也让我们的数据标准化了——我们不需要没有号码的联系人显示为NULL。telephone 表的字段信息如下:
contact_id
name (文本,例如座机号,工作手机等)
number
问题二:Email地址有同样的问题,因此我们也创建一个类似的 email 表:
contact_id
name (text such as home email, work email, etc.)
address
问题三:我们可能不想输入一个(地理位置的)地址,或者我们想输入多个地址,工作地,家里,度假住所等。因此我们需要一个新的 address 表:
contact_id
name (text such as home, office, etc.)
address1
address2
address3
city
region
zipcode
country
我们原来的 contact 表简化成:
id
title
firstname
lastname
gender
我们没有考虑到联系人的中间名字、出生日期、公司或职位。我们添加多少字段都没关系,我们很快会收到更新的需求要添加备注、纪念日、关系状态、社交媒体账号、内腿测量值、最喜欢的奶酪类型等字段。预测所有选项是不可能的,因此我们可能需要一个 otherdata 表,用来处理名字-值对。
对开发者或者系统管理员来说,检查数据库并不容易。程序逻辑会变得更慢、更复杂,因为利用单个 SELECT 和多个 JOIN 语句查询联系人数据不太实际。(你可以这么做,但是结果可能需要包含 telephone,email,和 address字段的每一种组合:如果有个联系人有三个电话号码,五个Email地址和两个住址,那么SQL查询将会产生30条结果。) 最后,全文搜索很困难。如果有人输入字符串”SitePoint”,我们必须检查所有的表,看看它是否为联系人名字、电话、Email或者住址的一部分,并且需要做相应的排序。
那么如果我们选择NoSQL呢?
我们的联系人数据关注的是人。他们难以预测,在不同的时间有不同的需求。使用NoSQL数据库,联系人列表将会从中受益。数据库将一个联系人的所有数据存储在一个单独的文档里的contacts 集合里。
在这个例子里,我们没有存储联系人的头衔或者性别,我们还添加了一些数据,而这些数据不需要应用到任何其他联系人。没关系——我们的NoSQL数据库不会介意,我们还可以随意添加或移除字段。
由于联系人数据在单独的文档里,我们可以用一条查询语句获取一部分或全部信息。全文搜索也变得简单;在MongoDB里,我们可以这样定义 contact 中的所有文本字段的索引:
db.contact.createIndex{{"$**": "text"}};
然后执行全文搜索:
db.contact.fond{{
    $text: { $search: "something" }}}

场景二:社交网络
社交网络可能使用类似的联系人数据存储,但是它会根据功能集合扩展,比如关系链、状态更新、发送消息和”赞“。这些功能可能会根据用户需求来实现或者移除——无法预测它们会怎样演进。
另外大部分的数据更新都来自单个源:用户。任何时候我们不太可能同时更新两条或更多记录,因此不要求类似事务控制的功能。
尽管有些用户可能认为,状态更新失败不可能引起系统崩溃或经济损失。应用程序的接口和性能比数据完整性优先级更高。
NoSQL看来是个好的方案。它允许我们快速地实现存储不同类型数据的功能。例如,可以用单个文档里的 status 集合替换所有用户的过时的状态更新。文档可能会变得很长,但我们可以获取数组的子集,比如最近的更新。每个用户的所有的历史状态记录都能被快速搜索到。
现在假设我们想在发布更新的时候引入表情符号选择。这涉及到给 update 数组里的新记录添加图引用。不像 SQL 存储,没必要把之前消息里的表情符号置为 NULL——我们的程序逻辑可以显示默认图片或者没有图片,如果没有设置表情符号的话。

场景三:仓库管理系统
考虑一个监控仓库货物的系统。我们需要记录:
送达仓库并被分配到指定位置的物品
仓库内物品的移动,也就是重新整理库存,以便让同样的物品放在相邻的位置
订单以及后续将物品搬出仓库,准备发货
我们的数据需求:
通用的物品信息,比如包装数量、尺寸和颜色等可被存储,但这些是我们可以识别并应用到任何物品上的离散数据。我们不太可能关注细节,例如笔记本处理器速度或者智能手机的电池寿命。
最小化出错的可能是必要的。我们不能让物品凭空消失或者移到已经有别的物品存放的位置。
简单来说,我们在记录物品从一个物理区域到另一个物理区域的转移——或者从A位置移走,放到B位置。这是同一个动作的两次更新。
我们需要一个具备强制数据完整性和事务支持的健壮存储系统。只有 SQL 数据库满足这些需求。