常用关系型数据库

  • Oracle:功能强大,主要缺点就是贵
  • MySQL:互联网行业中最流行的数据库,这不仅仅是因为MySQL的免费。可以说关系数据库场景中你需要的功能,MySQL都能很好的满足,后面详解部分会详细介绍MySQL的一些知识点
  • MariaDB:是MySQL的分支,由开源社区维护,MariaDB虽然被看作MySQL的替代品,但它在扩展功能、存储引擎上都有非常好的改进
  • PostgreSQL:也叫PGSQL,PGSQL类似于Oracle的多进程框架,可以支持高并发的应用场景,PG几乎支持所有的SQL标准,支持类型相当丰富。PG更加适合严格的企业应用场景,而MySQL更适合业务逻辑相对简单、数据可靠性要求较低的互联网场景。

常用非关系型数据库

  • Redis:提供了持久化能力,支持多种数据类型。Redis适用于数据变化快且数据大小可预测的场景。
  • MongoDB:一个基于分布式文件存储的数据库,将数据存储为一个文档,数据结构由键值对组成。MongoDB比较适合表结构不明确,且数据结构可能不断变化的场景,不适合有事务和复杂查询的场景。
  • HBase:建立在HDFS,也就是Hadoop文件系统之上的分布式面向列的数据库。类似于谷歌的大表设计,HBase可以提供快速随机访问海量结构化数据。在表中它由行排序,一个表有多个列族以及每一个列族可以有任意数量的列。 HBase依赖HDFS可以实现海量数据的可靠存储,适用于数据量大,写多读少,不需要复杂查询的场景。
  • Cassandra:一个高可靠的大规模分布式存储系统。支持分布式的结构化Key-value存储,以高可用性为主要目标。适合写多的场景,适合做一些简单查询,不适合用来做数据分析统计。
  • Pika:一个可持久化的大容量类Redis存储服务, 兼容五种主要数据结构的大部分命令。Pika使用磁盘存储,主要解决Redis大容量存储的成本问题。

NewSQL数据库(新一代关系型数据库)

  • TiDB:开源的分布式关系数据库,几乎完全兼容MySQL,能够支持水平弹性扩展、ACID事务、标准SQL、MySQL语法和MySQL协议,具有数据强一致的高可用特性。既适合在线事务处理,也适合在线分析处理。
  • OceanBase:OceanBase是蚂蚁金服的数据库,OB是可以满足金融级的可靠性和数据一致性要求的数据库系统。当你需要使用事务,并且数据量比较大,就比较适合使用OB。不过目前OB已经商业化,不再开源。

数据库事务特性

  • 原子性:是指事务由原子的操作序列组成,所有操作要么全部成功,要么全部失败回滚。
  • 一致性:是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以一致性状态。比如在做多表操作时,多个表要么都是事务后新的值,要么都是事务前的旧值。
  • 隔离性:是指多个用户并发访问数据库时,数据库为每个用户执行的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。事务的隔离级别我们稍后介绍。
  • 持久性:是指一个事务一旦提交并执行成功,那么对数据库中数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

事物并发问题与隔离级别

事务并发问题
  • 脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据,例如,账户A转帐给B500元,B余额增加后但事务还没有提交完成,此时如果另外的请求中获取的是B增加后的余额,这就发生了脏读,因为事务如果失败回滚时,B的余额就不应该增加。
  • 不可重复读:不可重复读是指对于数据库中某个数据,一个事务范围内多次查询返回了不同的数据值,这是由于在多次查询之间,有其他事务修改了数据并进行了提交。
  • 幻读:是指一个事务中执行两次完全相同的查询时,第二次查询所返回的结果集跟第一个查询不相同。与不可重复读的区别在于,不可重复读是对同一条记录,两次读取的值不同。而幻读是记录的增加或删除,导致两次相同条件获取的结果记录数不同。
隔离级别
  • 读未提交:也就是可以读取到其他事务未提交的内容,这是最低的隔离级别,这个隔离级别下,前面提到的三种并发问题都有可能发生。
  • 读已提交:就是只能读取到其他事务已经提交的数据。这个隔离级别可以解决脏读问题。
  • 可重复读:可以保证整个事务过程中,对同数据的多次读取结果是相同的。这个级别可以解决脏读和不可重复读的问题。MySQL默认的隔离级别就是可重复读。
  • 串行化:这是最高的隔离级别,所有事务操作都依次顺序执行。这个级别会导致并发度下降,性能最差。不过这个级别可以解决前面提到的所有并发问题。

事务分类

  • 扁平化事务:在扁平事务中,所有的操作都在同一层次,这也是我们平时使用最多的一种事务。它的主要限制是不能提交或者回滚事务的某一部分,要么都成功,要么都回滚。
  • 带保存点的扁平事务:为了解决第一种事务的弊端,就有了第二种带保存点的扁平事务。它允许事务在执行过程中回滚到较早的状态,而不是全部回滚。通过在事务中插入保存点,当操作失败后,可以选择回滚到最近的保存点处。
  • 链事务:可以看做是第二种事务的变种。它在事务提交时,会将必要的上下文隐式传递给下一个事务,当事务失败时就可以回滚到最近的事务。不过,链事务只能回滚到最近的保存点,而带保存点的扁平化事务是可以回滚到任意的保存点。
  • **嵌套事务:**由顶层事务和子事务构成,类似于树的结构。一般顶层事务负责逻辑管理,子事务负责具体的工作,子事务可以提交,但真正提交要等到父事务提交,如果上层事务回滚,那么所有的子事务都会回滚。
  • 分布式事务:是指分布式环境中的扁平化事务。
    • XA协议:是保证强一致性的刚性事务。实现方式有两段式提交和三段式提交。两段式提交需要有一个事务协调者来保证所有的事务参与者都完成了第一阶段的准备工作。如果协调者收到所有参与者都准备好的消息,就会通知所有的事务执行第二阶段提交。一般场景下两段式提交已经能够很好得解决分布式事务了,然而两阶段在即使只有一个进程发生故障时,也会导致整个系统存在较长时间的阻塞。三段式提交通过增加Pre-commit阶段来减少前面提到的系统阻塞的时间。三段式提交很少在实际中使用,简单了解就可以了。
    • TCC:是满足最终一致性的柔性事务方案。TCC采用补偿机制,核心思想是对每个操作,都要注册对应的确认和补偿操作。它分为三个阶段:Try阶段主要对业务系统进行检测及资源预留;Confirm阶段对业务系统做确认提交。Cancel阶段是在业务执行错误,执行回滚,释放预留的资源。
    • 消息事务:第三种方案是消息一致性方案。基本思路是将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么都成功要么都失败。下游应用订阅消息,收到消息后执行对应操作。
    • **GTS/Fescar:**阿里云中的全局事务服务GTS,对应的开源版本是Fescar。Fescar基于两段式提交进行改良,剥离了分布式事务方案对数据库在协议支持上的要求。使用Fescar的前提是分支事务中涉及的资源,必须是支持ACID事务的关系型数据库。分支的提交和回滚机制,都依赖于本地事务来保障。 Fescar的实现目前还存在一些局限,比如事务隔离级别最高支持到读已提交级别。

CAP定理

在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer’s theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (所有节点在同一时间具有相同的数据)
  • 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
  • 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  • CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

NoSQL的优点/缺点

优点:

  • 高可扩展性
  • 分布式计算
  • 低成本
  • 架构的灵活性,半结构化数据
  • 没有复杂的关系

缺点:

  • 没有标准化
  • 有限的查询功能(到目前为止)
  • 最终一致是不直观的程序

三个范式

  • 第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。

  • 第二范式(2NF):数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。

  • 第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如 果存在”A → B → C”的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系: 关键字段 → 非关键字段 x → 非关键字段y

Mysql

常用SQL语句

​ 推荐《mysql必知必会》这本书

mysql的基本数据类型
TINYINT 1 byte (-128,127) (0,255) 小整数值
SMALLINT 2 bytes (-32 768,32 767) (0,65 535) Sss大整数值
MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整数值
INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值
FLOAT 4 bytes (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值
DOUBLE 8 bytes (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值
DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TINYBLOB 0-255 bytes 不超过 255 个字符的二进制字符串
TINYTEXT 0-255 bytes 短文本字符串
BLOB 0-65 535 bytes 二进制形式的长文本数据
TEXT 0-65 535 bytes 长文本数据
MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据
MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据
LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据
LONGTEXT 0-4 294 967 295 bytes 极大文本数据
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 bytes ‘-838:59:59’/‘838:59:59’ HH:MM:SS 时间值或持续时间
YEAR 1 bytes 1901/2155 YYYY 年份值
DATETIME 8 bytes 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 4 bytes 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳
INT(INTEGER)

TINYINT,SMALLINT,MEDIUMINT,BIGINT同理。

int的长度是4字节, INT(M)的意思是现在最大宽度为M。如果你选择了zero fill,不足M位会给前面自动补0,如果不选,大于M位正常显示。索引如果不为了补0M指定多少都无所谓。。

DECIMAL

FLOAT 类型固定占用4个字节, DOUBLE 类型固定占用8个字节

DECIMAL(M,D) ,其中 M 表示最大位数,D 表示小数点右侧的位数。这里的“位”不是二进制的比特位,而是指十进制的数字的位数。

varchar和char

CHAR(n) 和 VARCHAR(n) 两者中的 n 含义均为该字段最大可容纳的字符数。

CHAR(n) 和 VARCHAR(n) 字段值的占用空间不是固定的,而是由实际存入的内容决定的

MySQL中主要的存储引擎
  • MyISAM是MySQL官方提供的存储引擎,其特点是支持全文索引,查询效率比较高,缺点是不支持事务、使用表级锁。
  • InnoDB在5.5版本后成为了Mysql的默认存储引擎,特点是支持ACID事务、支持外键、支持行级锁提高了并发效率
drop、deletetruncate区别?
  • delete和truncate只删除表的数据不删除表的结构
  • 速度,一般来说: drop> truncate >delete
  • delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效,如果有相应的trigger,执行的时候将被触发
  • truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger
MySQL中的锁
MyISAM使用表级锁
  • 表锁开销小,加锁快,不会出现死锁;但是锁的粒度大,发生锁冲突的概率高,并发访问效率比较低。
InnoDB使用行级锁
  • 行级锁开销大,加锁慢,有可能会出现死锁,不过因为锁定粒度最小,发生锁冲突的概率低,并发访问效率比较高。
共享锁

共享锁也就是读锁,其他事务可以读,但不能写。MySQL可以通过Lock In Share Mode语句显示使用共享锁。

排它锁

排他锁就是写锁,其他事务不能读取,也不能写。对于Update、Delete和INSERT语句,InnoDB会自动给涉及的数据集加排他锁,或者使用select for update显示使用排他锁。

乐观锁和悲观锁是什么?
  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
  • 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性
MySQL的存储过程与函数
什么是存储过程?
  • 存储过程是一些预编译的SQL语句。
  • 存储过程是一个预编译的代码块,执行效率比较高
  • 一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率
  • 可以一定程度上确保数据安全
存储过程的优缺点?

优点:

  • 执行效率比较高
  • 可以降低网络通信量,提高通信速率
  • 可以一定程度上确保数据安全

缺点:

  • 存储过程一般与数据库实现绑定,使用存储过程会降低程序的可移植性
为什么不推荐使用外键?

详见

优点:

  • 关系型数据库,外键的约束为我们保证了数据主从关系和产生的先后关系,级联操作为我们的update和delete带来了不少方便。

缺点:

  • 数据库需要维护外键的内部管理。
  • 外键等于把数据的一致性事务实现,全部交给数据库服务器完成;
  • 有了外键,当做一些涉及外键字段的增,删,更新操作之后,需要触发相关操作去检查,而不得不消耗资源
  • 外键还会因为需要请求对其他表内部加锁而容易出现死锁情况。
  • 总的来说就是性能问题,然后不易于表的变动和扩展。

限制:

  • 所有tables必须是InnoDB型,它们不能是临时表。
  • 在引用表中,必须有一个索引,外键列以同样的顺序被列在其中作为第一列。这样一个索引如果不存在,它必须在引用表里被自动创建。
  • 不支持对外键列的索引前缀。这样的后果之一是BLOB和TEXT列不被包括在一个外键中,这是因为对这些列的索引必须总是包含一个前缀长度
  • InnoDB不对那些外键或包含NULL列的被引用键值检查外键约束
mysql8.0的新特性
  • 默认字符集格式改为了UTF8

  • 增加了隐藏索引的功能,隐藏后的索引不会被查询优化器使用,可以使用这个特性用于性能调试

  • 支持了通用表表达式,使复杂查询中的嵌入表语句更加清晰

  • 新增了窗口函数的概念,它可以用来实现新的查询方式。窗口函数与 SUM、COUNT等集合函数类似,但不会将多行查询结果合并,而是将结果放在多行中。即窗口函数不需要GROUP BY。

    • 同时具有分组和排序的功能

    • 同时具有分组和排序的功能

    • <窗口函数> over (partition by <用于分组的列名> order by <用于排序的列名>)

MySQL调优

索引

索引是什么?

  • 索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。

索引的优缺点

优点:

  • 索引加快数据库的检索速度

  • 唯一索引可以确保每一行数据的唯一性

  • 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能

  • 因此索引比较适合用在读多写少的场景。

缺点:

  • 需要额外的磁盘空间来保存索引

  • 对于插入、更新、删除等操作由于更新索引会增加额外的开销

mysql有几种索引类型?

  • 唯一索引:就是索引列中的值必须是唯一的,但是允许出现空值。这种索引一般用来保证数据的唯一性,比如保存账户信息的表,每个账户的id必须保证唯一,如果重复插入相同的账户id时会MySQL返回异常。
  • 主键索引:是一种特殊的唯一索引,但是它不允许出现空值。
  • 普通索引:与唯一索引不同,它允许索引列中存在相同的值。例如学生的成绩表,各个学科的分数是允许重复的,就可以使用普通索引。
  • 联合索引:就是由多个列共同组成的索引。一个表中含有多个单列的索引并不是联合索引,联合索引是对多个列字段按顺序共同组成一个索引。应用联合索引时需要注意最左原则,就是Where查询条件中的字段必须与索引字段从左到右进行匹配。比如,一个用户信息表,用姓名和年龄组成了联合索引,如果查询条件是姓名等于张三,那么满足最左原则;如果查询条件是年龄大于20,由于索引中最左的字段是姓名不是年龄,所以不能使用这个索引。
  • 全文索引:前面提到了,MyISAM引擎中实现了这个索引,在5.6版本后InnoDB引擎也支持了全文索引,并且在5.7.6版本后支持了中文索引。全文索引只能在CHAR,VARCHAR,TEXT类型字段上使用,底层使用倒排索引实现。要注意对于大数据量的表,生成全文索引会非常消耗时间也非常消耗磁盘空间。

索引实现?

  • B+树实现:b+树比较适合用作’>’或’<’这样的范围查询,是MySQL中最常使用的一种索引实现。
  • R-tree:是一种用于处理多维数据的数据结构,可以对地理数据进行空间索引。不过实际业务场景中使用的比较少。
  • Hash:是使用散列表来对数据进行索引,Hash方式不像Btree那样需要多次查询才能定位到记录,因此Hash索引的效率高于B-tree,但是不支持范围查找和排序等功能.实际使用的也比较少。
  • FullText:就是我们前面提到的全文索引,是一种记录关键字与对应文档关系的倒排索引。

一手好 SQL 是如何炼成的?

Redis

详细用法可以看这里redis文档或者这里关于redis的基本操作

数据结构

五种基本类型
  • String字符串
    • session
    • kv缓存。比如分布式锁。
    • 数值计数计算器。DECR INCR DECRBY INCRBY
    • bitmap。存二进制数据,统计用户每天登陆情况,统计用户活跃数。
  • Hash哈希
    • 聚集数据
    • 详情页
  • List列表
    • 评论列表
    • 消息队列
    • 队列和栈数据结构的东西。
  • Set集合
    • 抽奖
    • 验证码
    • 扑克牌游戏
  • SortedSet有序集合
高级一点的数据类型
更高级一点的模块

redis持久化

同时开启RDBAOF,redis会使用AOF文件恢复而不使用RDB文件。

快照RDB

RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。

原理: redis会调用fork()产生一个子进程,子进程会把数据写入到一个临时的RDB文件,当子进程写完之后,用临时的RDB文件替换掉旧的RDB文件。

优点

  • 性能好
  • 恢复快

缺点

  • 两个备份时间点之间如果服务器宕机,中间的数据会丢失。

**配置(redis.conf)**:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# RDB文件名,默认为dump.rdb。
dbfilename dump.rdb

# 保存点可以设置多个。每60秒,如果数据发生了1000次以上的变动,Redis就会自动保存快照文件
save 60 1000 #60秒后至少1000个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动

# 禁用快照,注释所有save,或者在最后一条加上
save ""

# 默认Redis会采用LZF对数据压缩 yes打开,no关闭
rdbcompression yes

# 数据校验文件完整性,会损失10%左右性能,yes打开,no关闭
rdbchecksum yes

手动生成快照

  • save 。 同步生成RDB文件,会阻塞其它客户端请求,不建议使用
  • bgsave。
    • 调用BGSAVE会立刻返回ok
    • redis会产生一个子进程保存快照,并恢复主进程处理客户端请求
    • 使用LASTSAVE来查看操作是否成功
追加式文件 AOF

记录你的每一条操作指令,恢复数据其实就是执行一遍文件保存的指令。

优点

  • 比RDB可靠。可以制定不同的fsync策略。
  • 当AOF文件太大时,Redis会自动在后台进行重写。

缺点

  • 相同数据情况下,AOF会被RDB文件大。极端情况下,假设有一个运行了几年的redis服务,但是操作只有创建一个key,删除一个key,rdb最多会保存一个数据,但是aof文件会有非常多的数据。
  • 在某些fsync策略下,速度会比RDB慢。

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# 打开aof功能
appendonly yes

# 文件存放目录,与RDB共用。默认为当前工作目录。
dir ./

# 默认文件名为appendonly.aof
appendfilename "appendonly.aof"

# always是每次都会追加,everysec是一秒追加一次,no是不追加。。推荐一秒一次,丢失数据只丢一秒,性能也不会太慢。
# appendfsync always
appendfsync everysec
# appendfsync no
aof文件重写

日志重新解决的就是我上面描述的问题,假设有十万条命令的执行结果就是增加一个key,那么aof文件恢复会依次执行这十万条命令,就很浪费性能,所以redis支持后台重建aof文件。

工作原理:

  • Redis调用fork(),产生一个子进程。
  • 子进程把新的AOF写到一个临时文件里。
  • 主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全。
  • 当子进程完成文件的重写后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新AOF里。

重写配置

1
2
3
4
5
6
7
8
9
# Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。
# 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。
# 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 百分比设置为0会禁用这个功能
auto-aof-rewrite-percentage 0

主从和集群

  • Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
  • Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

redis面试问题

天下无难试之Redis面试题刁难大全

redis吊打面试官系列。。。

MongoDB

什么是MOngoDB?

  • MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
  • MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。