# 数据库

  • 数据库(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 文件,恢复数据。
  • 特点:
    • 新增数据的方式为批量写入磁盘,比逐行写入的效率更高。
    • 访问磁盘的大部分操作都是顺序读写,比随机读写快了两个数量级。
    • 稍微降低了读取速度。
  • 采用 LSM Tree 或类似原理的数据库举例:
    • MySQL 的 redo log
    • MongoDB 的 WiredTiger 存储引擎
    • ClickHouse 的 MergeTree 存储引擎
    • ES
    • Prometheus

# 索引

按索引的范围分类:

  • 稠密索引
    • :对每个数据都建立索引。
    • 例如:给每个数据分配一个唯一名称,然后在索引表中记录每个数据的磁盘存储地址。
  • 稀疏索引
    • :只对部分数据建立索引。
    • 例如:给每个数据分配一个递增的数字编号,并存储到磁盘的连续地址空间。此时,即使索引表中只记录了第 1 个数据的存储地址,也可以推算出第 n 个数据的存储地址。
    • 稀疏索引与稠密索引相比,建立的索引表更小,且不必每次修改数据都更新索引表,但查询耗时更久。

按索引的方向分类:

  • 正排索引
    • 原理:
      1. 当用户搜索一个字符串时,搜索引擎会逐个查询已有的文档,找出包含该字符串的所有文档。
      2. 然后建立索引:某个字符串,对应某个文档。
    • 这样建立索引的过程简单,但搜索速度慢。
  • 倒排索引
    • 原理:
      1. 事先建立索引:某个单词,对应某个文档的某个位置。
      2. 当用户搜索一个字符串时,先将它拆分成多个单词,然后根据索引定位文档。
    • 这样建立索引的过程复杂,但搜索速度快。
    • 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 命令。