时间:2021-07-01 10:21:17 帮助过:56人阅读
同一类型的文档存储为一个集合(collection),类似于关系型数据库中的表结构。然而,你可以在任意的文档中存储任意的数据,NoSQL数据库不会去进行比较。例如:
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", year: 2014, format: "ebook", price: 29.00, description: "Learn JavaScript from scratch!", rating: "5/5", review: [ { name: "A Reader", text: "The best JavaScript book I‘ve ever read." }, { name: "JS Expert", text: "Recommended to novice and expert developers alike." } ] }
SQL中的表结构具有严格的数据模式约束,因此存储数据很难出错。NoSQL存储数据更加灵活自由,但是也会导致数据不一致性问题的发生。
在关系型数据库中,除非你事先定义了表和字段的模式否则你无法向其中添加数据。模式中包含了许多的信息:
在进行数据的逻辑操作之前我们必须要定义数据模式。数据模式可以在后期进行更改,但是对于模式的大改将会是非常复杂的。
在NoSQL的数据库中,数据在任何时候都可以进行添加。不需要事先去定义文档和集合。例如在MongoDB中如下的操作将会在book
集合中重新创建一个文档如果之前没有创建。
db.book.insert( ISBN: 9780994182654, title: "Jump Start Git", author: "Shaumik Daityari", format: "ebook", price: 29.00 );
(MongoDB会在集合中为每一个文档添加一个独一无二的_id。如果你仍然想要定义索引,你也可以自己在之后定义)
一个NoSQL数据库更适合于那些不能够确定数据需求的的工程项目。也就是说,不要为自己的懒惰而制造麻烦:不在项目开始的时候设计一个好的数据存储模型在将来会带来一定的麻烦。
假设我们想要在书店的数据库中添加一项出版社信息。一个出版社会出版很多书,因此在数据库中我们创建了一个表publisher
:
id | name | country | |
---|---|---|---|
SP001 | SitePoint | Australia | feedback@sitepoint.com |
我们要在book
表中添加一个publisher_id
的字段,用于引用出版社信息中的id:
ISBN | title | author | format | price | publisher_id |
---|---|---|---|---|---|
9780992461225 | JavaScript: Novice to Ninja | Darren Jones | ebook | 29.00 | SP001 |
9780994182654 | Jump Start Git | Shaumik Daityari | ebook | 29.00 | SP001 |
这样的设计能够最小化数据的冗余,我们不需要为每一本书重复的添加出版社的所有信息—只需要去引用就可以了。这项技术叫做数据库的规范化,具有实际的意义。我们可以更改出版社信息而不用修改book
中的数据。
在NoSQL中我们也可以使用规范化技术。在book
集合中的文档:
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00, publisher_id: "SP001" }
引用publisher
集合中的一个文档
{ id: "SP001" name: "SitePoint", country: "Australia", email: "feedback@sitepoint.com" }
然而,在实际中我们并不会这样做。我们会更倾向于选择非规范化我们的文档为每一本书中都重复出版社的信息
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00, publisher: { name: "SitePoint", country: "Australia", email: "feedback@sitepoint.com" } }
这样会使查询更快,但是在更新出版社信息的记录变多时效率将会显著地下降。
SQL语言为查询提供了强大的JOIN操作。我们可以使用单个SQL语句在多个表中获取相关数据。例如:
SELECT book.title, book.author, publisher.name FROM book LEFT JOIN book.publisher_id ON publisher.id;
这条SQL语句会返回所有书的书名,作者和相关的出版社的名称。
在NoSQL中没有与JOIN相同的操作,对于具有SQL语言经验的人来说是非常令人震惊的。如果我们使用是上面的规范化的集合,我们需要取出book
集合中所有的文档,检索所有的publisher
的文档,并在程序中进行手动连接。这也是非规范化存在的原因之一。
大多数的数据库允许通过定义外键来进行数据库的完整性约束。我们的数据库能够保证:
publisher_id
都会对应于publisher
中的一个实体,publisher_id
与publisher
中的id对应,那么该出版社就不能被删除。数据模式确保了这些规则被数据库遵守。开发者或者用户不能添加、修改和移除一条记录,如果这些操作导致数据产生无效的数据或者单条无用记录。
在NoSQL数据库中没有数据完整性的约束选项。你可以存储任何你想要存储的数据。理想情况下,单个文档将是项目的所有信息的唯一来源。
在SQL数据库中,两条或者多条更新操作可以结合成一个事务(或者全部执行成功否则失败)执行。例如,假设我们的book数据库中包含了order
和stock
表。当一本书被订购之后,我们要在order
中添加一条记录并减少stock
中的库存数目。如果我们将两条更新操作分别执行,一条成功另一个失败---这将会导致数据库的不一致性。将两条更新操作绑定为一个事务确保了它们要么全部成功要么全部失败。
在NoSQL数据库中,对于一个文档的更新操作是原子性的。换句话说,如果你要更新一个文档中的三个值,要么三个值都更新成功要么它们保持不变。然而,对于操作多个文档时没有雨事务相对应的操作。在MongoDB中有一个操作是transaction-like options,但是,需要我们手动的加入到代码中。
增删改查是数据库的基本操作。本质上:
比较:
SQL | NoSQL |
---|---|
insert a new book record | |
INSERT INTO book ( ISBN, title, author)VALUES ( ‘9780992461256‘, ‘Full Stack JavaScript‘, ‘Colin Ihrig & Adam Bretz‘); |
db.book.insert({ ISBN: "9780992461256", title: "Full Stack JavaScript", author: "Colin Ihrig & Adam Bretz"}); |
update a book record | |
UPDATE bookSET price = 19.99WHERE ISBN = ‘9780992461256‘ |
db.book.update( { ISBN: ‘9780992461256‘ }, { $set: { price: 19.99 } }); |
return all book titles over $10 | |
SELECT title FROM bookWHERE price > 10; |
db.book.find( { price: { >: 10 } }, { _id: 0, title: 1 }); The second JSON object is known as a projection: it sets which fields are returned (_id is returned by default so it needs to be unset). |
count the number of SitePoint books | |
SELECT COUNT(1) FROM bookWHERE publisher_id = ‘SP001‘; |
db.book.count({ "publisher.name": "SitePoint"}); This presumes denormalized documents are used. |
return the number of book format types | |
SELECT format, COUNT(1) AS totalFROM bookGROUP BY format; |
db.book.aggregate([ { $group: { _id: "$format", total: { $sum: 1 } } }]); This is known as aggregation: a new set of documents is computed from an original set. |
delete all SitePoint books | |
DELETE FROM bookWHERE publisher_id = ‘SP001‘; Alternatively, it’s possible to delete the publisher record and have this cascade to associated book records if foreign keys are specified appropriately. |
db.book.remove({ "publisher.name": "SitePoint"}); |
或许最具有争议性的比较是:通常情况下,NoSQL比SQL语言更快。这并没有什么好震惊的,NoSQL中更加简单的非规范化存储允许我们在一次查询中得到特定项的所有信息。不需要使用SQL中复杂的JOIN操作。
也就是说,你的项目的设计和数据的需求会有很大的影响。一个好的SQL数据库的设计的表现一定会比一个设计不好的NoSQL数据库性能好很多,反之亦然。
随着数据量的增长,我们或许会发现有必要将负载分配到到不同的服务器上。对于基于SQL语言的开发的系统是非常困难的。如何分配相关的数据?集群是一种最简单可能的解决方案,多个服务器访问同一个中央存储器—及时是这样也会有许多的问题。
NoSQL的简单的数据模型能够简化其过程,许多NoSQL数据库在一开始就构建了解决大规模数据的功能。这仅仅是一个概括,如果你遇到了这样的问题应该去寻求专家的帮助。
最后,我们考虑一下安全性和系统性的问题。流行的NoSQL数据库已经存在好几年了,它们展现的问题可能会比成熟的关系型数据库多。许多问题都已经被发现了,但是所有的问题都指向了同一个问题:了解程度。
开发人员和系统管理员对于管理新型数据库有很少的经验,因此会产生许多问题。选择NoSQL是因为感觉它比较新颖,或者你想要避免数据模式的设计,都会在将来带来一些问题。
SQL和NoSQL数据库只是用不同的方式来完成相同的事情。我们可能会先选择其中之一然后更换到另一个上,但是在选择之前制定一个计划将会节约许多的时间和金钱。
适合使用SQL开发的项目:
适合使用NoSQL开发的项目:
在我们的例子中,一个关系型数据库是一种更好的选择— 尤其是当我们需要引入强大的事务支持的电子商务设备。在接下来的一篇文章中,我们将讨论更多的项目场景,并确定使用一个SQL或NoSQL数据库是否是最好的解决方案。
关系型数据库与NoSQL的对比
标签:and ext 结构 出版 nat 过程 名称 数据模型 操作