Skip to content

数据库概念

什么是关系数据库

关系数据库是一种基于关系模型的数据库管理系统。它使用表格来存储数据,每个表格都有一个唯一的名称,每个表格中的数据都按照预定义的模式进行组织。关系数据库的核心概念包括表格、行、列和主键。

  • mysql
  • postgresql

什么是非关系数据库

非关系数据库是一种不使用表格来存储数据的数据库管理系统。它通常使用文档、键值对或图形等数据模型来存储数据。非关系数据库的核心概念包括文档、键值对和图。

  • redis
  • mongodb

MongoDB 文档数据库

MongoDB是一种基于文档的非关系数据库,它使用BSON(类似JSON的二进制格式)来存储数据。MongoDB的核心概念包括数据库、集合和文档。

创建数据库

javascript
use mydatabase

创建集合

javascript
db.createCollection("users")

插入文档

javascript
db.users.insertOne({
  name: "John Doe",
  age: 30,
  email: "john.doe@example.com"
})

查询文档

javascript
// 查询所有文档
db.users.find()

// 查询特定条件的文档
db.users.find({ age: { $gt: 25 } })

// 查询特定字段的文档
db.users.find({}, { name: 1, email: 1 })

更新文档

javascript
// 更新单个文档
db.users.updateOne(
  { name: "John Doe" },
  { $set: { age: 31 } }
)

// 更新多个文档
db.users.updateMany(
  { age: { $lt: 30 } },
  { $inc: { age: 1 } }
)

删除文档

javascript
// 删除单个文档
db.users.deleteOne({ name: "John Doe" })

// 删除多个文档
db.users.deleteMany({ age: { $gt: 30 } })

创建索引

javascript
// 创建单字段索引
db.users.createIndex({ email: 1 })

// 创建复合索引
db.users.createIndex({ name: 1, age: -1 })

// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })

Redis 键值对数据库

Redis是一种基于键值对的非关系数据库,它支持多种数据结构,包括字符串、哈希、列表、集合和有序集合。Redis的核心概念包括键、值和数据结构。

字符串操作

bash
# 设置键值对
SET name "John Doe"

# 获取键值
GET name

# 递增数值
SET counter 0
INCR counter

哈希操作

bash
# 设置哈希字段
HSET user:1 name "John Doe" age 30 email "john.doe@example.com"

# 获取哈希字段
HGET user:1 name

# 获取所有哈希字段
HGETALL user:1

列表操作

bash
# 向列表左侧添加元素
LPUSH tasks "Task 1"
LPUSH tasks "Task 2"

# 向列表右侧添加元素
RPUSH tasks "Task 3"

# 从列表左侧弹出元素
LPOP tasks

# 从列表右侧弹出元素
RPOP tasks

集合操作

bash
# 向集合添加元素
SADD users "John Doe"
SADD users "Jane Doe"

# 获取集合所有元素
SMEMBERS users

# 判断元素是否在集合中
SISMEMBER users "John Doe"

有序集合操作

bash
# 向有序集合添加元素
ZADD scores 100 "John Doe"
ZADD scores 95 "Jane Doe"

# 获取有序集合所有元素
ZRANGE scores 0 -1

# 获取有序集合元素的分数
ZSCORE scores "John Doe"

什么是索引

索引是一种数据结构,用于加快数据库查询的速度。它通过在表格的列上创建索引来存储指向数据行的指针。索引可以是唯一的或非唯一的,根据需要进行创建。

mysql 索引

sql
CREATE INDEX index_name ON table_name (column_name);

什么是唯一索引

唯一索引是一种索引,它要求索引列中的值是唯一的。如果尝试插入或更新数据,导致唯一索引列中的值重复,数据库将拒绝操作并抛出错误。唯一索引可以用于确保表格中的数据是唯一的,例如用户表中的用户名或电子邮件地址。

sql
CREATE UNIQUE INDEX index_name ON table_name (column_name);

什么是主键索引

主键索引是一种特殊的唯一索引,它要求索引列中的值是唯一的,并且不能为空。主键索引通常用于标识表格中的每一行数据,例如用户表中的用户ID。

sql
CREATE PRIMARY KEY (column_name);

什么是外键索引

外键索引是一种索引,它用于加速与其他表格之间的关联查询。它通过在一个表格的列上创建索引,来引用另一个表格的主键列。外键索引可以用于确保数据的完整性和一致性,例如在订单表格中引用用户表格的用户ID。

mysql 外键索引

sql
CREATE INDEX index_name ON table_name (foreign_key_column);

什么是联合索引

联合索引是一种索引,它包含多个列。它可以用于加速多列查询,例如在订单表格中查询某个用户的所有订单。联合索引的创建和使用与单列索引类似,只是在创建索引时指定多个列。

sql
CREATE INDEX index_name ON table_name (column1, column2, ...);

什么是索引覆盖查询

索引覆盖查询是一种查询,它只使用索引来满足查询条件,而不需要访问表格中的数据行。这可以显著提高查询性能,因为它避免了磁盘 I/O 操作。要执行索引覆盖查询,查询条件中的所有列都必须包含在索引中。例如,假设我们有一个订单表格,它包含订单ID、用户ID、订单日期和订单金额等列。如果我们创建了一个联合索引 (user_id, order_date),那么查询订单表格中某个用户在某个日期范围内的所有订单,就可以只使用索引来满足查询条件,而不需要访问表格中的数据行。

sql
SELECT order_id, order_date, order_amount
FROM orders
WHERE user_id = 123
  AND order_date BETWEEN '2023-01-01' AND '2023-01-31';

什么是索引合并查询

索引合并查询是一种查询,它使用多个索引来满足查询条件。这可以显著提高查询性能,因为它避免了扫描整个表格。要执行索引合并查询,查询条件中的所有列都必须包含在索引中。例如,假设我们有一个订单表格,它包含订单ID、用户ID、订单日期和订单金额等列。如果我们创建了一个联合索引 (user_id, order_date) 和一个单列索引 (order_amount),那么查询订单表格中某个用户在某个日期范围内的所有订单金额大于100的订单,就可以使用这两个索引来满足查询条件。

sql
SELECT order_id, order_date, order_amount
FROM orders
WHERE user_id = 123
  AND order_date BETWEEN '2023-01-01' AND '2023-01-31'
  AND order_amount > 100;

什么是索引前缀查询

索引前缀查询是一种查询,它只使用索引的前缀来满足查询条件。这可以显著提高查询性能,因为它避免了扫描整个索引。要执行索引前缀查询,查询条件中的列必须是索引的前缀列。例如,假设我们有一个订单表格,它包含订单ID、用户ID、订单日期和订单金额等列。如果我们创建了一个联合索引 (user_id, order_date),那么查询订单表格中某个用户在某个日期范围内的所有订单,就可以只使用索引的前缀 (user_id) 来满足查询条件,而不需要扫描整个索引。

sql
SELECT order_id, order_date, order_amount
FROM orders
WHERE user_id = 123
  AND order_date BETWEEN '2023-01-01' AND '2023-01-31';

什么是索引下推查询

索引下推查询是一种查询,它将索引的过滤条件下推到存储引擎层,而不是在应用层进行过滤。这可以显著提高查询性能,因为它避免了扫描整个表格。要执行索引下推查询,查询条件中的所有列都必须包含在索引中。例如,假设我们有一个订单表格,它包含订单ID、用户ID、订单日期和订单金额等列。如果我们创建了一个联合索引 (user_id, order_date),那么查询订单表格中某个用户在某个日期范围内的所有订单金额大于100的订单,就可以将索引的过滤条件 (order_amount > 100) 下推到存储引擎层,而不需要在应用层进行过滤。

sql
SELECT order_id, order_date, order_amount
FROM orders
WHERE user_id = 123
  AND order_date BETWEEN '2023-01-01' AND '2023-01-31'
  AND order_amount > 100;

什么是索引合并排序查询

索引合并排序查询是一种查询,它使用多个索引来满足查询条件,并对结果进行排序。这可以显著提高查询性能,因为它避免了扫描整个表格和排序操作。要执行索引合并排序查询,查询条件中的所有列都必须包含在索引中。例如,假设我们有一个订单表格,它包含订单ID、用户ID、订单日期和订单金额等列。如果我们创建了一个联合索引 (user_id, order_date) 和一个单列索引 (order_amount),那么查询订单表格中某个用户在某个日期范围内的所有订单金额大于100的订单,并按订单金额降序排序,就可以使用这两个索引来满足查询条件,并对结果进行排序。

sql
SELECT order_id, order_date, order_amount
FROM orders
WHERE user_id = 123
  AND order_date BETWEEN '2023-01-01' AND '2023-01-31'
  AND order_amount > 100
ORDER BY order_amount DESC;

什么是主键

主键是一种约束,它用于确保一个表格中的每一行数据都是唯一的。例如,假设我们有一个用户表格,它包含用户ID、用户名、密码和电子邮件等列。如果我们在用户表格中创建一个主键约束,将用户ID列作为主键,那么就可以确保每个用户都有一个唯一的ID。如果我们尝试在用户表格中插入一个重复的用户ID,就会触发主键约束错误。

sql
CREATE TABLE users (
  id INT PRIMARY KEY,
  username VARCHAR(50),
  password VARCHAR(50),
  email VARCHAR(50)
);

什么是外键

外键是一种约束,它用于确保一个表格中的数据与另一个表格中的数据保持一致。例如,假设我们有一个订单表格和一个用户表格,它们分别包含订单ID、用户ID、订单日期和订单金额等列。如果我们在订单表格中创建一个外键约束,将用户ID列与用户表格中的ID列关联起来,那么就可以确保每个订单都有一个有效的用户ID。如果我们尝试在订单表格中插入一个不存在的用户ID,就会触发外键约束错误。

sql
CREATE TABLE orders (
  order_id INT PRIMARY KEY,
  user_id INT,
  order_date DATE,
  order_amount DECIMAL(10,2),
  FOREIGN KEY (user_id) REFERENCES users(id)
);

什么是事务

事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。事务具有ACID特性,确保数据的一致性和可靠性。

ACID特性

  • 原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么全部执行,要么全部不执行。
  • 一致性(Consistency):事务执行前后,数据库的完整性约束没有被破坏。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不能被其他事务干扰。
  • 持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对其执行结果有任何影响。

事务示例

sql
-- 开启事务
START TRANSACTION;

-- 执行操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- 提交事务
COMMIT;

-- 回滚事务(如果出现错误)
ROLLBACK;

什么是数据库范式

数据库范式是数据库设计的一套规则,用于减少数据冗余,提高数据一致性。常见的范式包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和鲍依斯-科得范式(BCNF)。

第一范式(1NF)

第一范式要求数据库表的每一列都是不可分割的原子值,即每一列的值都是单一值,不能是集合、数组或嵌套结构。

第二范式(2NF)

第二范式要求数据库表中的非主键列完全依赖于主键,而不是部分依赖于主键的一部分。这意味着如果主键是复合主键,非主键列必须依赖于整个主键,而不是主键的一部分。

第三范式(3NF)

第三范式要求数据库表中的非主键列不传递依赖于主键,即非主键列之间不能有依赖关系。这意味着非主键列只能依赖于主键,而不能依赖于其他非主键列。

鲍依斯-科得范式(BCNF)

鲍依斯-科得范式是第三范式的进一步规范化,要求每个决定因素都是候选键。这意味着在数据库表中,每个非平凡函数依赖的左边都是候选键。

什么是视图

视图是从一个或多个表中导出的虚拟表,它本身不存储数据,而是根据定义动态生成数据。视图可以简化复杂查询,提高数据安全性,并提供数据的逻辑独立性。

创建视图

sql
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

使用视图

sql
SELECT * FROM view_name;

什么是存储过程

存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户可以通过指定存储过程的名字并给出参数来执行它。

创建存储过程

sql
CREATE PROCEDURE procedure_name (IN parameter1 INT, OUT parameter2 VARCHAR(50))
BEGIN
  -- 存储过程体
  SELECT column1 INTO parameter2 FROM table_name WHERE id = parameter1;
END;

执行存储过程

sql
CALL procedure_name(1, @result);
SELECT @result;

什么是触发器

触发器是一种特殊的存储过程,它在特定的数据库操作(如INSERT、UPDATE、DELETE)发生时自动执行。触发器可以用于实现复杂的业务规则和数据完整性约束。

创建触发器

sql
CREATE TRIGGER trigger_name
AFTER INSERT ON table_name
FOR EACH ROW
BEGIN
  -- 触发器体
  INSERT INTO audit_table (action, table_name, row_id) VALUES ('INSERT', 'table_name', NEW.id);
END;

什么是数据库备份与恢复

数据库备份是将数据库中的数据和日志文件复制到另一个位置的过程,以便在数据丢失或损坏时恢复数据。数据库恢复是将备份的数据恢复到数据库中的过程。

数据库备份类型

  • 完全备份:备份整个数据库,包括所有数据和日志文件。
  • 增量备份:备份自上次备份以来更改的数据。
  • 差异备份:备份自上次完全备份以来更改的数据。

数据库备份示例

sql
-- 完全备份
mysqldump -u username -p database_name > backup.sql

-- 恢复数据库
mysql -u username -p database_name < backup.sql

什么是数据库性能优化

数据库性能优化是通过调整数据库配置、优化查询语句和索引结构等方式,提高数据库的响应速度和吞吐量。

数据库性能优化方法

  • 优化查询语句:使用EXPLAIN分析查询语句,避免全表扫描,使用合适的索引。
  • 优化索引结构:创建合适的索引,避免过多的索引,定期重建和优化索引。
  • 调整数据库配置:调整数据库的内存分配、缓存大小和并发连接数等参数。
  • 分区表:将大型表分成多个小表,提高查询性能。
  • 读写分离:将读操作和写操作分离到不同的数据库服务器,提高并发性能。

什么是数据库安全

数据库安全是保护数据库中的数据不被未经授权的访问、修改或破坏的过程。数据库安全包括身份认证、授权、加密和审计等方面。

数据库安全措施

  • 身份认证:使用用户名和密码或其他认证方式验证用户身份。
  • 授权:为用户分配不同的权限,限制用户对数据库的访问。
  • 加密:对数据库中的数据进行加密,防止数据泄露。
  • 审计:记录用户对数据库的操作,以便追踪和审计。
  • 防火墙:使用防火墙限制对数据库服务器的访问。

什么是数据库锁机制

数据库锁机制是数据库管理系统用于控制并发访问的一种机制,它可以防止多个事务同时修改同一数据,确保数据的一致性和完整性。

锁的类型

  • 共享锁(S锁):允许事务读取数据,但不允许修改数据。多个事务可以同时持有共享锁。
  • 排他锁(X锁):允许事务读取和修改数据。只有一个事务可以持有排他锁。
  • 意向锁:用于表示事务对数据的锁定意向,包括意向共享锁(IS锁)和意向排他锁(IX锁)。
  • 行级锁:锁定数据行,允许其他事务访问同一表中的其他行。
  • 表级锁:锁定整个表,防止其他事务访问表中的任何行。

锁的粒度

  • 行级锁:粒度最细,并发性能最高,但开销也最大。
  • 页级锁:粒度介于行级锁和表级锁之间。
  • 表级锁:粒度最粗,并发性能最低,但开销也最小。

什么是数据库并发控制

数据库并发控制是数据库管理系统用于控制多个事务并发执行的一种机制,它可以防止多个事务之间的相互干扰,确保数据的一致性和完整性。

并发控制的方法

  • 锁机制:使用锁来控制并发访问。
  • 时间戳排序:使用时间戳来决定事务的执行顺序。
  • 乐观并发控制:假设事务之间不会发生冲突,只有在提交时才检查冲突。
  • 悲观并发控制:假设事务之间会发生冲突,使用锁来防止冲突。

什么是数据库分片

数据库分片是一种将大型数据库分成多个小型数据库的技术,它可以提高数据库的性能和可扩展性。

分片的类型

  • 水平分片:将表中的行分成多个分片,每个分片存储不同的行。
  • 垂直分片:将表中的列分成多个分片,每个分片存储不同的列。
  • 混合分片:结合水平分片和垂直分片的优点。

分片的策略

  • 范围分片:根据数据的范围进行分片。
  • 哈希分片:根据数据的哈希值进行分片。
  • 列表分片:根据数据的列表值进行分片。

什么是数据库缓存

数据库缓存是一种将数据库中的数据存储在内存中的技术,它可以提高数据库的性能和响应速度。

缓存的类型

  • 查询缓存:缓存查询结果,避免重复执行相同的查询。
  • 数据缓存:缓存数据库中的数据,避免重复读取磁盘。
  • 索引缓存:缓存数据库中的索引,提高索引的访问速度。

缓存的策略

  • LRU(最近最少使用):淘汰最近最少使用的缓存项。
  • LFU(最不经常使用):淘汰最不经常使用的缓存项。
  • FIFO(先进先出):淘汰最早进入缓存的缓存项。

什么是数据库读写分离

数据库读写分离是一种将数据库的读操作和写操作分离到不同的数据库服务器的技术,它可以提高数据库的并发性能和可扩展性。

读写分离的架构

  • 主从复制:主数据库处理写操作,从数据库处理读操作。
  • 读写分离中间件:使用中间件来路由读操作和写操作。

什么是数据库分库分表

数据库分库分表是一种将大型数据库分成多个小型数据库和表的技术,它可以提高数据库的性能和可扩展性。

分库分表的策略

  • 垂直分库:将不同的表分配到不同的数据库。
  • 垂直分表:将一个表中的列分配到不同的表。
  • 水平分库:将一个表中的行分配到不同的数据库。
  • 水平分表:将一个表中的行分配到不同的表。

什么是数据库中间件

数据库中间件是一种位于应用程序和数据库之间的软件,它可以提供负载均衡、读写分离、分库分表等功能,提高数据库的性能和可扩展性。

数据库中间件的类型

  • 代理中间件:作为应用程序和数据库之间的代理,处理数据库请求。
  • 分片中间件:提供分库分表功能,将大型数据库分成多个小型数据库。
  • 缓存中间件:提供缓存功能,提高数据库的性能和响应速度。

非关系数据库与关系数据库的对比

数据模型

  • 关系数据库:使用表格模型,数据以行和列的形式存储。
  • 非关系数据库:使用文档、键值对、图形等模型,数据以灵活的形式存储。

数据一致性

  • 关系数据库:强一致性,支持ACID特性。
  • 非关系数据库:最终一致性,支持BASE特性(基本可用、软状态、最终一致性)。

可扩展性

  • 关系数据库:垂直扩展为主,水平扩展较困难。
  • 非关系数据库:水平扩展为主,容易扩展到多个节点。

查询语言

  • 关系数据库:使用SQL语言,支持复杂查询和事务。
  • 非关系数据库:使用查询API或自定义查询语言,支持简单查询和批量操作。

适用场景

  • 关系数据库:适用于需要强一致性和复杂查询的场景,如金融、电商等。
  • 非关系数据库:适用于需要高可扩展性和灵活数据模型的场景,如社交、日志等。

数据库选型建议

选择关系数据库的场景

  • 需要强一致性和ACID特性。
  • 需要复杂查询和事务支持。
  • 数据结构相对稳定,变化不大。
  • 数据量不大,不需要水平扩展。

选择非关系数据库的场景

  • 需要高可扩展性和水平扩展。
  • 数据结构灵活,变化较大。
  • 需要处理大量非结构化数据。
  • 需要高并发读写性能。

数据库设计原则

关系数据库设计原则

  • 遵循数据库范式,减少数据冗余。
  • 合理设计主键和外键,确保数据完整性。
  • 合理设计索引,提高查询性能。
  • 避免过度规范化,权衡性能和可维护性。

非关系数据库设计原则

  • 根据数据模型选择合适的非关系数据库类型。
  • 合理设计文档结构,避免嵌套过深。
  • 合理设计键结构,提高查询性能。
  • 考虑数据的分布和分片策略,提高可扩展性。

数据库迁移

数据库迁移是将数据从一个数据库迁移到另一个数据库的过程,它可以用于升级数据库、更换数据库类型或优化数据库性能。

迁移的类型

  • 同类型迁移:将数据从一个关系数据库迁移到另一个关系数据库,或从一个非关系数据库迁移到另一个非关系数据库。
  • 跨类型迁移:将数据从关系数据库迁移到非关系数据库,或从非关系数据库迁移到关系数据库。

迁移的步骤

  • 评估源数据库和目标数据库的差异。
  • 设计迁移方案,包括数据转换和映射。
  • 执行迁移操作,包括数据导出、转换和导入。
  • 验证迁移结果,确保数据的完整性和一致性。

数据库监控

数据库监控是对数据库的性能、可用性和安全性进行监控的过程,它可以帮助管理员及时发现和解决数据库问题。

监控的指标

  • 性能指标:CPU使用率、内存使用率、磁盘I/O、查询响应时间等。
  • 可用性指标:数据库在线时间、故障次数、恢复时间等。
  • 安全性指标:登录失败次数、未授权访问次数、数据泄露事件等。

监控的工具

  • 内置监控工具:数据库自带的监控工具,如MySQL的Performance Schema、MongoDB的mongostat等。
  • 第三方监控工具:第三方提供的监控工具,如Prometheus、Grafana、Zabbix等。