# 数据库
- 数据库(Database)是一种用于存储、管理数据的软件,供用户读写。
- 数据库通常比普通文件存储数据的效率高很多,因为数据库采用了合适的数据结构来存储数据,还提供了便捷的管理方法。
- 数据结构包括数据的组织方式、数据之间的联系方式。
- 很多数据库不是简单的一个软件,而是复杂的系统,称为数据库管理系统(Database Management System ,DBMS)。比如部署成 C/S 架构、部署成分布式集群。
- 数据库通常比普通文件存储数据的效率高很多,因为数据库采用了合适的数据结构来存储数据,还提供了便捷的管理方法。
# 分类
# 关系型数据库
:Relational Database Management System(RDBMS)
- 采用 SQL 语言进行操作,因此又称为 SQL 数据库。
- 特点:
- 以二维表格的形式存储数据,每行为一条数据,每列为一个字段。
- 每行数据拥有相同的字段,结构相同。
- 通常选取一个在各行数据中取值都不同的字段(比如编号)作为主键,以便区分各行数据。
- 优点:
- 比网状、层状等数据结构更简单。
- 可使用通用的 SQL 语言进行操作。
- 缺点:
- 数据表结构是固定的,不方便修改、扩展。
- 关系型数据库举例:
- SQLite :很轻量级,不需要安装就可以直接使用。
- MySQL :开源,由 Oracle 公司发布。
- Oracle :收费,由 Oracle 公司发布。
- PostgreSQL :开源。
- Access :由微软公司发布。
- SQL Server :由微软公司发布。
- DB2 :收费,由 IBM 公司发布。
- Aurora :AWS 云提供的数据库,优化了分布式架构,兼容 MySQL、PostgreSQL 。
- PolarDB :阿里云提供的数据库,借鉴了 Aurora 。
# 非关系型数据库
:Non-Relational Database
- 又称为 NoSQL 数据库(Not Only SQL),即不仅仅是 SQL 的数据库。
- 特点:
- 采用与 SQL 数据库不同的数据结构,从而在某些方面比 SQL 数据库的能力更强。
- 但可能缺乏其它方面的能力,比如不支持事务,因此用途比较窄。
主要分类:
- 键值对数据库
- 比如 Redis 。
- 列式数据库
- :将数据按字段分成一列列存储,因此按字段读写的速度比行式存储快很多。
- 比如 Cassandra、Hbase 。
- 文档型数据库
- :采用结构化的文档格式存储数据,比如 JSON 格式。
- 比如 MongoDB 。
- 图结构数据库
- 对象存储数据库
- 时序数据库(TSDB):每个数据都有一个时间戳 timestamp ,按时间顺序线性排列。
- 比如 Influxdb、OpenTSDB、Graphite、Prometheus、Elasticsearch 。
# 其它分类
- NewSQL
- :新一代的关系型数据库。依然支持 SQL 操作,但增加了像 NoSQL 数据库的横向扩展性。
- 与 RDBMS 相比,更适合处理大量处理。
- 与 NoSQL 相比,兼容 SQL 操作,容易让传统项目沿用。
- OLTP(Online Transaction Processing ,在线事务处理)
- :一种数据库使用场景,侧重于进行事务操作。分布式部署时,还需要保证一致性。
- 处理大规模数据时,数据库的容量、速度、可靠性等性能通常不能兼得,通常分为 OLTP、OLAP 两种场景。
- 数据库举例:
- MySQL 等传统 SQL 数据库
- OLAP(Online Analytical Processing ,在线分析处理)
- :一种数据库使用场景,侧重于进行多维的复杂查询。
- 例如一个商品可能存在类型(服装、食品、家具)、品牌、时间(年、月、日)、地点(国家、省、市)等多种维度的信息。如果使用 SQL 数据库,则需要建立关系复杂的多张数据表,查询效率低。
- 数据库举例:
- Druid
- Kylin
- Presto
- MPP(Massively Parallel Processing ,大规模并行处理)
- :一种软件架构,指将大规模任务分配到多个服务器上并行处理,然后汇总结果。
- 常用于 OLAP 。
- 数据库举例:
- ClickHouse
- DorisDB
- GreenPlum
- HTAP(Hybrid Transaction/Analytical Processing ,混合事务/分析处理)
- :同时擅长 OLTP 和 OLAP 。
- 数据库举例:
- TiDB
# SQL
:结构化查询语言(Structured Query Language),是关系型数据库的标准操作语言。
- 属于脚本语言。
- 不同关系型数据库软件支持的 SQL 语法存在差异。
# 分类
SQL 按用途分为多个子集:
数据定义语言(Data Define Language ,DDL)
- 主要是 CREATE、DROP、ALTER、TRUNCATE、RENAME 命令,用于增删改数据库、数据表、索引、用户、函数等对象。
- 例:
CREATE DATABASE db1;
数据操作语言(Data Manipulation Language ,DML)
- 主要是 INSERT、UPDATE、DELETE 命令,用于增删改数据。
数据查询语言(Data Query Language ,DQL)
- 主要是 SELECT 命令,用于查询数据。
数据控制语言(Data Control Language ,DCL)
- 主要是 GRANT、REVOKE 命令,用于控制权限。
事务控制语言(Transaction Control Language ,TCL)
- 主要是 COMMIT、ROLLBACK 命令,用于控制事务。
# 语法
- 不区分大小写。
- 用
--
声明单行注释,用/* */
声明多行注释。 - 每条语句必须以分号 ; 结尾。
- 输入一条语句时,可以多次按回车换行输入,直到输入分号才结束。
- 字符串的定界符可以是以下几种:
- 不使用定界符,此时字符串不能包含空格。
- 使用单引号 ' ,此时支持转义字符。
- MySQL 中,可以使用双引号 " 。
- MySQL 中,如果字符串与 MySQL 的保留字冲突,则必须使用反引号 ` 作为定界符。
# 存储算法
# B+ tree
- ext3、ext4 文件系统基于 H tree 索引文件,与 B tree 类似。
- NTFS 文件系统基于 B+ tree 索引文件。
- MySQL 的 InnoDB 存储引擎基于 B+ tree 存储数据并进行索引。
- 每行数据以 id:row 键值对形式存储,根据主键 id 即可索引。
- 内部节点存放在内存中,需要访问叶子节点时才进行磁盘 IO 。
# Hash Table
:哈希表。
- 特点:
- 适合随机读写。对数据寻址的时间复杂度为 O(1) ,比 B Tree 的时间复杂度 O(n) 快很多。
- 不支持顺序读写,因此磁盘 IO 的耗时较久。
# LSM Tree
:Log Structured Merge Tree 。
- 原理:
- 新增数据时,先保存在内存的 memtable 中。等 memtable 缓冲了一定数量的数据之后,再 flush 到磁盘。
- memtable 的结构类似于红黑树,有序地存储数据。
- flush 时,会在磁盘新建一个 segment 文件,然后以 append 方式顺序写入数据。
- segment 文件内的数据是有序的,因此可以只建立稀疏索引。
- segment 文件内的数据不支持修改、删除。
- 删除数据时,会给 segment 文件中的数据加上一个墓碑(tombstone)标记,不允许被查询到,但不会释放磁盘空间。
- 更新数据时,会当作新数据添加,并给旧数据加上 tombstone 标记。
- segment 文件会被自动合并:将多个小文件拷贝合并成一个大文件,然后删掉旧文件。从而节省打开大量文件的开销。
- 合并时,不会拷贝原 segment 中带有 tombstone 标记的数据。
- 为了避免内存断电而丢失数据,会将内存中新增的数据同时写入预写日志(Write Ahead Log ,WAL)文件,作为备份。
- WAL 文件也是顺序写入磁盘,且结构简单,因此开销低。
- 如果程序异常终止,重启时会读取 WAL 文件,恢复数据。
- 新增数据时,先保存在内存的 memtable 中。等 memtable 缓冲了一定数量的数据之后,再 flush 到磁盘。
- 特点:
- 新增数据的方式为批量写入磁盘,比逐行写入的效率更高。
- 访问磁盘的大部分操作都是顺序读写,比随机读写快了两个数量级。
- 稍微降低了读取速度。
- 采用 LSM Tree 或类似原理的数据库举例:
- MySQL 的 redo log
- MongoDB 的 WiredTiger 存储引擎
- ClickHouse 的 MergeTree 存储引擎
- ES
- Prometheus
# 索引
按索引的范围分类:
- 稠密索引
- :对每个数据都建立索引。
- 例如:给每个数据分配一个唯一名称,然后在索引表中记录每个数据的磁盘存储地址。
- 稀疏索引
- :只对部分数据建立索引。
- 例如:给每个数据分配一个递增的数字编号,并存储到磁盘的连续地址空间。此时,即使索引表中只记录了第 1 个数据的存储地址,也可以推算出第 n 个数据的存储地址。
- 稀疏索引与稠密索引相比,建立的索引表更小,且不必每次修改数据都更新索引表,但查询耗时更久。
按索引的方向分类:
- 正排索引
- 原理:
- 当用户搜索一个字符串时,搜索引擎会逐个查询已有的文档,找出包含该字符串的所有文档。
- 然后建立索引:某个字符串,对应某个文档。
- 这样建立索引的过程简单,但搜索速度慢。
- 原理:
- 倒排索引
- 原理:
- 事先建立索引:某个单词,对应某个文档的某个位置。
- 当用户搜索一个字符串时,先将它拆分成多个单词,然后根据索引定位文档。
- 这样建立索引的过程复杂,但搜索速度快。
- ES 等大部分搜索引擎都支持倒排索引,以大幅提高全文搜索的速度。
- 原理:
# 相关概念
- CRUD :指数据库的 Create(增)、Read(查)、Update(改)、Delete(删)四种基本操作。
- ODBC :开放数据库连接(Open Database Connectivity),是微软公司提出的一种传统的数据库 API 规范,可以兼容不同类型的数据库。
- Navicat :一个数据库客户端,属于 GUI 软件,闭源收费。
- 支持连接多种数据库,包括 MySQL、Oracle、PostgreSQL、SQLite、SQL Server、MariaDB、MongoDB 等。
- DBeaver :一个数据库客户端,属于 GUI 软件,开源。
- 采用 Java 开发,基于 JDBC 连接数据库。因此支持的数据库类型比 Navicat 更多,只需下载对应的 jar 包驱动。
# DorisDB
:一个 NewSQL 数据库,采用 MPP 架构、列式存储。
- 官方文档 (opens new window)
- 历史:
- 百度公司开源了 Palo 数据库,2018 年进入 Apache 孵化器,改名为 Doris 。
- 后来部分开发人员离职创业,创建了鼎石公司,发行闭源的 DorisDB 软件。2021 年改名为 StarRocks 并开源。
- 特点:
- 支持用 mysql 客户端连接,兼容部分 SQL 命令。
- 支持创建外部表:反向代理 MySQL、ES 等后端的数据,供用户只读。
- 组件:
- fe :前端,采用 Java 开发,负责反向代理 be 、维护集群状态、接收用户的请求。
- be :后端,采用 Golang 开发,负责存储数据、执行 fe 传来的命令。
- broker :可选组件,供 be 读写 HDFS、S3 等存储系统,实现数据导出、导入、备份的功能。
- 数据表设计:
- 每个数据表(Table)在逻辑上划分为 n≥1 个分区(Partition),
- 每个分区在存储时,根据哈希值划分为 n≥1 个桶(Bucket、Tablet)。
- 每个 Bucket 独立存储在磁盘,是同步数据、负载均衡的最小单位。
- 建议每个 Bucket 最多存储 10G 数据。
- 默认给每个分区保存 3 个副本(replication),且同一 Bucket 的多个副本必须存储到不同 IP 的 be 实例。
- 已创建的分区,不支持修改 Bucket 数。
# TiDB
:一个 NewSQL 数据库,擅长 HTAP 。
- 官方文档 (opens new window)
- 发音为
/taɪdiːbi:/
。 - 2017 年由中国 PingCAP 公司开源,采用 Golang 开发。
- 支持用 mysql 5.7 客户端连接,兼容大部分 SQL 命令。