四、选择

    先简单回顾下数据库的分类。

    数据库通常分为层次式数据库、网络式数据库和关系式数据库三种。而不同的数据库是按不同的数据结构来联系和组织的。在当今的互联网中,最常见的数据库模型主要有两种:关系型数据库和非关系型数据库。

    关系型数据库模型是把复杂的数据结构归结为简单的二元关系(即二维表格形式)。在关系型数据库中,对数据的操作几乎全部建立在一个或多个关系表格上,通过对这些关联的表格分类、合并、连接或选取等运算来实现数据库的管理。主流关系型数据库有 Oracle、MySQL、MariaDB、SqlServer、Access、PostgreSQL、DB2 等。其中个人感觉 PostgreSQL 功能十分强大,虽是关系型数据库,但支持 json 和 Hstore 字段,兼有事务和文档特性,只是性能就差了点。

    NoSQL 意味着 Not only SQL。面对超大规模和高并发的 SNS(社交网络服务) 类型的 web2.0 纯动态网站,传统的关系型数据库显得有些力不从心,比如表的横向扩展等。NoSQL 数据库作为传统关系型数据库的有效补充,在特定的场景下可以发挥出难以想象的高效率和高性能。主流的非关系型数据库分为键值存储数据库 (Memcached、Redis 等),列存储数据库 (HBase 等),图形数据库 (Neo4j 等),面向文档数据库 (MongoDB、CouchDB 等)。

    介绍完分类,接下来就简单说一下各自的使用场景。

    特点:

    • 提供事务,使两个或两个以上的成功或失败的数据更改作为一个原子单元;
    • 高度组织化结构化数据;
    • 数据和关系都存储在单独的表中;
    • 鼓励标准化减少数据冗余;
    • 支持多表查询;
    • 强制数据完整性;
    • 严格的一致性;
    • 支持扩展(横向扩展有些痛苦);
    • 结构化查询语言(SQL);
    • 诞生 40 年之多,十分成熟,有足够的支持;

    从其特点分析,可看出其适合有明确的定义,规范比较明确的项目。比如在线商城和银行系统等。该类系统需要具备强制数据完整性以及事务支持的健壮存储系统。可以试想一下如果去 ATM 机取钱,ATM 机没有吐钱,但是后台数据库已经把钱减掉了,会是一种什么样的体验呢?

    特点:

    • 没有声明性查询语言;
    • 没有预定义的模式;
    • 键-值对存储,列存储,文档存储,图形数据库;
    • 最终一致性,而非 ACID 属性;
    • 非结构化和不可预知的数据;
    • CAP 定理 ;
    • 高性能,高可用性和可伸缩性;

    就客户管理系统来说,假如刚开始使用关系型数据库建一个联系人的表,表字段有主键 id、姓名 name、电话 telephone、邮箱 email、地址 address。那么问题来了,现在有联系人有三个电话号码(住宅座机、移动电话、工作电话)需要输入,这时就要考虑单独创建一个 telephone 表,这样就不受限制了,也让我们的数据标准化了。新建 telephone 表结构:联系人 contact_id、号码类型 name、号码 num。email 与 address 也存在同样的问题,address 的情况更加复杂,这里不再展开。对关系型数据库来说,Schema 是固定不变的,而我们事先是不能预测所有字段的,比如刚才的联系人表,很快我们会发现当前字段不能满足,比如要添加性别 gender、年龄 age、生日 birthday 等字段,那么最后就导致需要加一个 otherdata 表。数据又是碎片化的,当查询一个联系人时,如果该联系人有 3 个电话号码、2 个 email 地址和 5 个地址,那么 SQL 查询需要检查所有表,并将产生 325=30 条结果,使得全文搜索很困难。

    面对这种情况,如果选择 NoSQL 数据库,联系人列表将从中受益。数据库将一个联系人的所有数据存储在一个单独的文档里的 contacts 集合里。

    如果这时需要添加一些数据,这些数据没有必要应用到之前的联系人,NoSQL 数据库就可以随意添加或移除字段。联系人数据存储在单独的文档中,也使得全文搜索变得简单。

    介绍完 SQL 与 NoSQL 数据库的基本概念,就该回到正题啦,介绍下 Node 嵌入式数据库,SQLite 同样也有 SQL 与 NoSQL 之分。

    其中使用最多的应该算 node-sqlite3 和 NeDB 了,两者的区别很明显,前者是 SQL 数据库,后者是 NoSQL 数据库。另外,sqlite3 相对 NeDB 要重一些,性能也要差一点,使用 SQL 语句失去了 js 直接操作 json 的简便,API 也相对复杂很多。而 NeDB 只提供了基本的 CURD 操作,只能用于小型应用,大场景并不适用,数据加载到内存中进行操作,不适合内存非常紧张的应用,目前作者也没有给出具体的内存控制方法。。