数据库原理与MySQL vs PostgreSQL
数据库基础
什么是数据库?
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。数据库管理系统(DBMS)是管理和操作数据库的软件。
数据库的主要特点:
- 数据持久化:数据可以长期保存
- 数据共享:多个用户可以同时访问数据
- 数据独立性:数据与应用程序相对独立
- 数据一致性:保证数据的一致性和完整性
- 数据安全性:提供访问控制和数据保护
数据库类型
关系型数据库(RDBMS):
- MySQL:开源,广泛使用
- PostgreSQL:开源,功能强大
- Oracle:商业数据库,企业级
- SQL Server:微软的数据库
- SQLite:轻量级嵌入式数据库
非关系型数据库(NoSQL):
- MongoDB:文档数据库
- Redis:键值数据库
- Cassandra:列式数据库
- Neo4j:图数据库
数据库模型
1. 层次模型(Hierarchical Model)
- 树形结构
- 一对多关系
2. 网状模型(Network Model)
- 图结构
- 多对多关系
3. 关系模型(Relational Model)
- 表结构
- 基于数学集合理论
- 最常用的模型
4. 对象模型(Object Model)
- 面向对象
- 对象关系映射(ORM)
SQL 基础
SQL 语言分类
1. DDL(Data Definition Language,数据定义语言)
CREATE:创建数据库、表、索引ALTER:修改表结构DROP:删除数据库、表、索引TRUNCATE:清空表数据
2. DML(Data Manipulation Language,数据操作语言)
SELECT:查询数据INSERT:插入数据UPDATE:更新数据DELETE:删除数据
3. DCL(Data Control Language,数据控制语言)
GRANT:授予权限REVOKE:撤销权限
4. TCL(Transaction Control Language,事务控制语言)
COMMIT:提交事务ROLLBACK:回滚事务SAVEPOINT:设置保存点
基本 SQL 语句
创建表:
1 | CREATE TABLE users ( |
插入数据:
1 | INSERT INTO users (username, email, password) |
查询数据:
1 | -- 基本查询 |
更新数据:
1 | UPDATE users |
删除数据:
1 | DELETE FROM users WHERE id = 1; |
SQL 连接(JOIN)
内连接(INNER JOIN):
1 | SELECT u.username, o.order_id, o.amount |
左连接(LEFT JOIN):
1 | SELECT u.username, o.order_id, o.amount |
右连接(RIGHT JOIN):
1 | SELECT u.username, o.order_id, o.amount |
全连接(FULL OUTER JOIN):
1 | -- MySQL 不支持 FULL OUTER JOIN,可以使用 UNION |
自连接(Self Join):
1 | SELECT e1.name AS employee, e2.name AS manager |
子查询
标量子查询:
1 | SELECT * FROM users |
关联子查询:
1 | SELECT * FROM orders o1 |
EXISTS 子查询:
1 | SELECT * FROM users u |
IN 子查询:
1 | SELECT * FROM users |
数据库设计原则
数据库范式
第一范式(1NF):
- 每个字段都是不可分割的原子值
- 每个字段都有唯一名称
- 每个记录都是唯一的
示例(不符合 1NF):
1 | 用户表 |
符合 1NF:
1 | 用户表 |
第二范式(2NF):
- 满足 1NF
- 非主键字段完全依赖于主键(不能部分依赖)
示例(不符合 2NF):
1 | 订单详情表 |
符合 2NF:
1 | 订单详情表 |
第三范式(3NF):
- 满足 2NF
- 非主键字段不能传递依赖于主键
示例(不符合 3NF):
1 | 员工表 |
符合 3NF:
1 | 员工表 |
BCNF(Boyce-Codd 范式):
- 满足 3NF
- 每个决定因素都是候选键
反范式化(Denormalization):
- 为了提高查询性能,故意违反范式
- 需要权衡数据一致性和查询性能
ER 模型(实体-关系模型)
实体(Entity):
- 具有独立存在意义的对象
- 例如:用户、订单、产品
属性(Attribute):
- 实体的特征
- 例如:用户的姓名、邮箱
关系(Relationship):
- 实体之间的联系
- 例如:用户和订单是一对多关系
ER 图示例:
1 | 用户(1)------< 订单(N) |
数据库设计步骤
需求分析
- 了解业务需求
- 确定数据实体和关系
概念设计
- 绘制 ER 图
- 识别实体、属性、关系
逻辑设计
- 将 ER 图转换为表结构
- 规范化设计
- 设计索引
物理设计
- 选择存储引擎
- 设计分区策略
- 优化性能
实施和维护
- 创建数据库和表
- 建立索引
- 持续优化
MySQL 原理
MySQL 架构
MySQL 架构层次:
- 连接层:处理客户端连接
- 服务层:SQL 解析、优化、执行
- 存储引擎层:数据存储和检索
- 文件系统层:数据文件存储
MySQL 存储引擎
InnoDB(默认引擎):
- 特点:
- 支持事务(ACID)
- 支持外键
- 支持行级锁
- 支持崩溃恢复
- 适用场景:事务性应用,需要高并发
- 存储:表数据和索引存储在 .ibd 文件中
MyISAM:
- 特点:
- 不支持事务
- 不支持外键
- 支持表级锁
- 查询速度快
- 适用场景:只读应用,日志记录
- 存储:.frm(表结构)、.MYD(数据)、.MYI(索引)
Memory(HEAP):
- 特点:
- 数据存储在内存中
- 速度快但数据易丢失
- 适用场景:临时表,缓存
对比:
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事务支持 | ✓ | ✗ |
| 外键支持 | ✓ | ✗ |
| 锁粒度 | 行级锁 | 表级锁 |
| 崩溃恢复 | ✓ | ✗ |
| 全文索引 | 5.6+ | ✓ |
| 查询速度 | 较慢 | 较快 |
| 写入速度 | 较慢 | 较快 |
MySQL 索引
什么是索引?
索引是数据库中用于快速查找数据的数据结构,类似于书籍的目录。
索引的类型:
1. B-Tree 索引(默认):
1 | -- 创建普通索引 |
2. 哈希索引:
- Memory 引擎支持
- 只支持等值查询
- 不支持范围查询
3. 全文索引:
1 | -- 创建全文索引 |
4. 空间索引(R-Tree):
- 用于地理空间数据
- MyISAM 和 InnoDB 5.7+ 支持
索引的优势:
- 加快查询速度
- 加快排序和分组
- 唯一索引保证数据唯一性
索引的劣势:
- 占用存储空间
- 降低写入速度(需要维护索引)
- 索引过多会影响性能
索引使用原则:
- 经常查询的列:WHERE、JOIN、ORDER BY 子句中的列
- 选择性高的列:不同值较多的列
- 避免在小表上建索引:小表全表扫描可能更快
- 避免在频繁更新的列上建索引:维护索引开销大
- 使用复合索引时注意顺序:最左匹配原则
索引失效的情况:
1 | -- 1. 使用函数 |
MySQL 事务
事务的特性(ACID):
1. 原子性(Atomicity):
- 事务中的所有操作要么全部成功,要么全部失败
- 通过 undo log 实现
2. 一致性(Consistency):
- 事务执行前后数据库保持一致状态
- 通过应用层逻辑和约束保证
3. 隔离性(Isolation):
- 并发事务之间相互隔离
- 通过锁机制实现
4. 持久性(Durability):
- 事务提交后,数据永久保存
- 通过 redo log 实现
事务隔离级别:
1. READ UNCOMMITTED(读未提交):
- 最低隔离级别
- 可能读取到未提交的数据(脏读)
2. READ COMMITTED(读已提交):
- 只能读取已提交的数据
- 可能出现不可重复读
- Oracle、SQL Server 默认级别
3. REPEATABLE READ(可重复读):
- 同一事务中多次读取结果一致
- 可能出现幻读
- MySQL InnoDB 默认级别(通过 MVCC 解决幻读)
4. SERIALIZABLE(串行化):
- 最高隔离级别
- 完全隔离,避免所有问题
- 性能最差
隔离级别对比:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ UNCOMMITTED | ✓ | ✓ | ✓ |
| READ COMMITTED | ✗ | ✓ | ✓ |
| REPEATABLE READ | ✗ | ✗ | ✓ |
| SERIALIZABLE | ✗ | ✗ | ✗ |
设置隔离级别:
1 | -- 查看当前隔离级别 |
并发问题:
1. 脏读(Dirty Read):
1 | 事务 A:UPDATE users SET balance = balance - 100 WHERE id = 1; -- 未提交 |
2. 不可重复读(Non-Repeatable Read):
1 | 事务 A:SELECT balance FROM users WHERE id = 1; -- 读取 1000 |
3. 幻读(Phantom Read):
1 | 事务 A:SELECT COUNT(*) FROM users WHERE age > 25; -- 返回 10 |
MySQL 锁机制
锁的类型:
1. 按粒度分类:
- 表级锁:锁住整个表(MyISAM)
- 行级锁:锁住特定行(InnoDB)
- 页级锁:锁住一页数据
2. 按性质分类:
- 共享锁(S 锁,读锁):允许其他事务读取,不允许写入
- 排他锁(X 锁,写锁):不允许其他事务读取和写入
3. 按意图分类:
- 意向共享锁(IS 锁)
- 意向排他锁(IX 锁)
行锁的类型:
1. Record Lock(记录锁):
- 锁住单行记录
2. Gap Lock(间隙锁):
- 锁住索引记录之间的间隙
- 防止幻读
3. Next-Key Lock(临键锁):
- Record Lock + Gap Lock
- 锁住记录和前面的间隙
死锁:
死锁示例:
1 | -- 事务 A |
死锁预防:
- 按相同顺序访问资源
- 尽量减少事务时间
- 使用较低的隔离级别
- 为表添加合理的索引
死锁检测:
1 | -- 查看死锁日志 |
MySQL 日志
1. 错误日志(Error Log):
- 记录 MySQL 运行错误
- 位置:
/var/log/mysql/error.log
2. 查询日志(Query Log):
- 记录所有 SQL 语句
- 用于调试和审计
3. 慢查询日志(Slow Query Log):
- 记录执行时间超过阈值的查询
1
2
3-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2; -- 2 秒
4. 二进制日志(Binlog):
- 记录所有数据变更操作
- 用于主从复制和数据恢复
1
2
3-- 查看 binlog
SHOW BINARY LOGS;
SHOW BINLOG EVENTS IN 'mysql-bin.000001';
5. 重做日志(Redo Log):
- InnoDB 特有的日志
- 记录事务的物理变更
- 用于崩溃恢复
6. 撤销日志(Undo Log):
- InnoDB 特有的日志
- 记录事务的逻辑变更
- 用于回滚和 MVCC
MVCC(多版本并发控制)
什么是 MVCC?
MVCC 通过保存数据的历史版本,实现读操作不加锁,提高并发性能。
实现原理:
- 版本链:每行数据有多个版本,通过指针链接
- ReadView:事务读取时创建快照,决定能看到哪些版本
- undo log:存储历史版本数据
优势:
- 读操作不加锁,提高并发
- 读写不冲突
- 减少死锁
示例:
1 | 时间线: |
MySQL 查询优化
执行计划(EXPLAIN):
1 | EXPLAIN SELECT * FROM users WHERE username = 'john'; |
优化技巧:
1. 使用索引:
1 | -- 创建合适的索引 |
*2. 避免 SELECT :
1 | -- 不好的做法 |
3. 使用 LIMIT:
1 | SELECT * FROM users LIMIT 10; |
4. 优化 JOIN:
1 | -- 确保 JOIN 条件有索引 |
5. 使用 EXISTS 代替 IN:
1 | -- 如果子查询结果集很大,使用 EXISTS 可能更快 |
6. 避免在 WHERE 子句中使用函数:
1 | -- 不好的做法 |
PostgreSQL 原理
PostgreSQL 特点
PostgreSQL 的优势:
- 标准兼容性:高度符合 SQL 标准
- 功能丰富:支持复杂数据类型、自定义函数、触发器
- 扩展性:支持多种扩展
- 并发控制:使用 MVCC 实现高并发
- 可靠性:数据一致性和完整性保证强
- 开源:完全开源,无许可证限制
PostgreSQL vs MySQL:
| 特性 | PostgreSQL | MySQL |
|---|---|---|
| SQL 标准 | 高度兼容 | 部分兼容 |
| 数据类型 | 丰富(数组、JSON、几何类型等) | 相对简单 |
| 事务支持 | 完整 | InnoDB 支持 |
| 全文搜索 | 内置 | MyISAM 支持 |
| 窗口函数 | 支持 | 8.0+ 支持 |
| JSON 支持 | 原生支持 | 5.7+ 支持 |
| 性能 | 复杂查询性能好 | 简单查询性能好 |
| 扩展性 | 扩展插件丰富 | 相对较少 |
PostgreSQL 数据类型
数值类型:
1 | SMALLINT -- 2 字节 |
字符串类型:
1 | CHAR(10) -- 固定长度 |
日期时间类型:
1 | DATE -- 日期 |
布尔类型:
1 | BOOLEAN -- true/false |
数组类型:
1 | CREATE TABLE users ( |
JSON 类型:
1 | CREATE TABLE products ( |
PostgreSQL 索引
索引类型:
1. B-Tree 索引(默认):
1 | CREATE INDEX idx_username ON users(username); |
2. 哈希索引:
1 | CREATE INDEX idx_email_hash ON users USING HASH(email); |
3. GiST 索引(通用搜索树):
- 用于全文搜索、几何数据
4. GIN 索引(广义倒排索引):
- 用于数组、全文搜索、JSON
1
CREATE INDEX idx_content_gin ON articles USING GIN(to_tsvector('english', content));
5. BRIN 索引(块范围索引):
- 用于大型表,按块存储
部分索引:
1 | -- 只对满足条件的行创建索引 |
表达式索引:
1 | -- 对表达式结果创建索引 |
PostgreSQL 并发控制
PostgreSQL 使用 MVCC:
- 与 MySQL InnoDB 类似,但实现方式不同
- 使用元组(tuple)版本管理
- 通过事务 ID(XID)判断可见性
事务隔离级别:
1 | -- 查看隔离级别 |
PostgreSQL 隔离级别:
- READ UNCOMMITTED:实际上等同于 READ COMMITTED
- READ COMMITTED:默认级别
- REPEATABLE READ:通过快照实现
- SERIALIZABLE:真正的串行化
PostgreSQL 高级特性
窗口函数:
1 | -- 计算每个部门的平均工资 |
公共表表达式(CTE):
1 | WITH RECURSIVE tree AS ( |
数组操作:
1 | -- 数组元素操作 |
JSON 操作:
1 | -- JSON 查询 |
自定义函数:
1 | -- PL/pgSQL 函数 |
触发器:
1 | -- 创建触发器函数 |
数据库设计原则
命名规范
表命名:
- 使用复数形式或明确含义:
users,orders,order_items - 使用下划线分隔:
user_profiles - 避免使用关键字:不使用
user,order等 SQL 关键字
字段命名:
- 使用小写字母和下划线:
user_id,created_at - 布尔字段使用
is_,has_前缀:is_active,has_permission - 外键使用
表名_id格式:user_id,order_id
索引命名:
- 普通索引:
idx_字段名,如idx_username - 唯一索引:
uk_字段名,如uk_email - 主键索引:
pk_表名,如pk_users - 外键索引:
fk_表名_字段名,如fk_orders_user_id
字段设计原则
1. 选择合适的数据类型:
- 数值类型:根据范围选择 INT、BIGINT
- 字符串类型:固定长度用 CHAR,可变长度用 VARCHAR
- 日期时间:使用 TIMESTAMP 或 DATETIME
- 布尔值:使用 BOOLEAN 或 TINYINT(1)
2. 使用 NOT NULL 约束:
1 | CREATE TABLE users ( |
3. 设置默认值:
1 | CREATE TABLE users ( |
4. 使用 AUTO_INCREMENT:
1 | CREATE TABLE users ( |
主键和外键设计
主键选择:
- 自增主键:简单、高效(推荐)
- UUID:分布式系统,但性能较差
- 业务主键:有意义的值,但不推荐
外键设计:
1 | CREATE TABLE orders ( |
外键约束选项:
ON DELETE CASCADE:删除父记录时自动删除子记录ON DELETE SET NULL:删除父记录时将外键设为 NULLON DELETE RESTRICT:禁止删除有子记录的父记录ON UPDATE CASCADE:更新父记录主键时同步更新子记录
索引设计原则
1. 主键自动创建索引:
1 | PRIMARY KEY (id) -- 自动创建主键索引 |
2. 外键创建索引:
1 | FOREIGN KEY (user_id) REFERENCES users(id); -- 应该在 user_id 上创建索引 |
3. 经常查询的字段创建索引:
1 | CREATE INDEX idx_username ON users(username); |
4. 复合索引注意顺序:
1 | -- 使用最左匹配原则 |
5. 避免过多索引:
- 每个索引都需要维护,过多索引会影响写入性能
- 一般建议每个表不超过 5-10 个索引
表设计最佳实践
1. 避免大宽表:
- 将不常用的字段拆分到扩展表
- 提高查询效率
2. 合理使用垂直拆分:
1 | 用户基础表(user_basic) |
3. 合理使用水平拆分(分表):
- 按时间分表:
orders_2024,orders_2025 - 按哈希分表:
users_0,users_1,users_2
4. 使用软删除:
1 | CREATE TABLE users ( |
5. 添加审计字段:
1 | CREATE TABLE users ( |
常见面试题
1. 数据库三范式是什么?
答案:
- 第一范式(1NF):每个字段都是原子值,不可再分
- 第二范式(2NF):满足 1NF,且非主键字段完全依赖于主键
- 第三范式(3NF):满足 2NF,且非主键字段不能传递依赖于主键
示例:
1 | 不符合 3NF: |
2. 事务的 ACID 特性是什么?
答案:
- 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败
- 一致性(Consistency):事务执行前后数据库保持一致状态
- 隔离性(Isolation):并发事务之间相互隔离
- 持久性(Durability):事务提交后数据永久保存
3. MySQL 的隔离级别有哪些?分别解决了什么问题?
答案:
- READ UNCOMMITTED:可能读取未提交数据(脏读)
- READ COMMITTED:只能读取已提交数据,解决脏读
- REPEATABLE READ:同一事务多次读取结果一致,解决不可重复读
- SERIALIZABLE:完全隔离,解决所有问题,但性能最差
MySQL InnoDB 默认是 REPEATABLE READ,通过 MVCC 解决了幻读问题。
4. 索引的类型有哪些?索引什么时候会失效?
答案:
索引类型:
- B-Tree 索引(默认)
- 哈希索引
- 全文索引
- 空间索引
索引失效情况:
- 在 WHERE 子句中使用函数:
WHERE YEAR(date) = 2024 - 类型转换:
WHERE id = '1'(id 是数字类型) - 使用
NOT、!=、<> LIKE以%开头:WHERE name LIKE '%john'- 复合索引未使用最左前缀
- 使用
OR连接条件(除非所有列都有索引)
5. MySQL InnoDB 和 MyISAM 的区别?
答案:
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事务支持 | ✓ | ✗ |
| 外键支持 | ✓ | ✗ |
| 锁粒度 | 行级锁 | 表级锁 |
| 崩溃恢复 | ✓ | ✗ |
| 全文索引 | 5.6+ | ✓ |
| 查询缓存 | ✗ | ✓ |
| 存储文件 | .ibd | .frm, .MYD, .MYI |
| 适用场景 | 事务性应用 | 只读应用 |
6. 什么是 MVCC?它是如何实现的?
答案:
MVCC(Multi-Version Concurrency Control)是多版本并发控制。
实现原理:
- 版本链:每行数据有多个版本,通过指针链接
- ReadView:事务读取时创建快照,决定能看到哪些版本
- undo log:存储历史版本数据
优势:
- 读操作不加锁,提高并发
- 读写不冲突
- 减少死锁
7. 什么是死锁?如何避免死锁?
答案:
死锁是指两个或多个事务相互等待对方释放资源,导致无法继续执行。
避免方法:
- 按相同顺序访问资源
- 尽量减少事务时间
- 使用较低的隔离级别
- 为表添加合理的索引
- 使用
SELECT ... FOR UPDATE时指定超时
8. 如何优化慢查询?
答案:
- 使用 EXPLAIN 分析执行计划
- 创建合适的索引
- 避免 SELECT *
- 优化 JOIN 查询:确保 JOIN 条件有索引
- 使用 LIMIT 限制结果集
- 避免在 WHERE 子句中使用函数
- 使用覆盖索引
- 合理使用分页:使用游标分页代替 OFFSET
9. 数据库分库分表的策略?
答案:
垂直拆分:
- 按业务模块拆分:用户库、订单库
- 按表字段拆分:基础表、扩展表
水平拆分:
- 按时间分表:
orders_2024,orders_2025 - 按哈希分表:
user_id % 4,分成 4 张表 - 按范围分表:
user_id 1-1000000一张表
分库分表中间件:
- ShardingSphere
- MyCat
- TDDL
10. 主从复制原理?
答案:
MySQL 主从复制流程:
- 主库将数据变更记录到 binlog
- 从库的 I/O 线程连接主库,读取 binlog
- 从库将 binlog 写入 relay log
- 从库的 SQL 线程读取 relay log,重放 SQL 语句
- 从库数据与主库同步
复制方式:
- 异步复制:主库不等待从库确认
- 半同步复制:至少一个从库确认
- 全同步复制:所有从库确认
11. 数据库连接池的作用?
答案:
连接池用于管理和复用数据库连接,避免频繁创建和销毁连接。
优势:
- 减少连接建立时间
- 控制连接数量
- 提高性能
- 资源复用
常用连接池:
- Java:HikariCP、Druid、C3P0
- Python:SQLAlchemy、pymysql
- Node.js:mysql2、pg
12. PostgreSQL 和 MySQL 的主要区别?
答案:
| 特性 | PostgreSQL | MySQL |
|---|---|---|
| SQL 标准 | 高度兼容 | 部分兼容 |
| 数据类型 | 丰富(数组、JSON、几何类型) | 相对简单 |
| 全文搜索 | 内置支持 | MyISAM 支持 |
| 窗口函数 | 完整支持 | 8.0+ 支持 |
| JSON 支持 | 原生 JSONB | 5.7+ 支持 |
| 扩展性 | 扩展插件丰富 | 相对较少 |
| 性能 | 复杂查询性能好 | 简单查询性能好 |
| 事务 | MVCC 实现 | InnoDB MVCC |
| 许可证 | PostgreSQL 许可证 | GPL/商业 |
13. 如何设计一个高可用的数据库架构?
答案:
- 主从复制:一主多从,读写分离
- 双主复制:两个主库互相复制(需解决冲突)
- 分库分表:水平扩展
- 缓存层:Redis 缓存热点数据
- 负载均衡:读写分离,负载均衡
- 监控告警:实时监控数据库状态
- 备份恢复:定期备份,测试恢复流程
14. 索引的底层数据结构是什么?
答案:
B-Tree 索引:
- MySQL InnoDB 使用 B+Tree
- 非叶子节点存储键值,叶子节点存储数据
- 支持范围查询和排序
哈希索引:
- 使用哈希表
- 只支持等值查询
- O(1) 查询时间复杂度
B+Tree vs B-Tree:
- B+Tree 非叶子节点不存储数据,只存储键值
- B+Tree 叶子节点通过指针连接,方便范围查询
- B+Tree 更适合磁盘存储(减少 I/O)
15. 如何设计一个订单表?
答案:
1 | CREATE TABLE orders ( |
总结
核心要点:
数据库基础:
- 理解数据库基本概念和类型
- 掌握 SQL 语言(DDL、DML、DCL、TCL)
- 熟悉数据库设计原则和范式
MySQL:
- 存储引擎(InnoDB、MyISAM)
- 索引原理和使用
- 事务和隔离级别
- 锁机制和 MVCC
- 查询优化
PostgreSQL:
- 高级数据类型(数组、JSON)
- 丰富的索引类型
- 窗口函数和 CTE
- 自定义函数和触发器
数据库设计:
- 遵循范式化设计
- 合理的索引设计
- 主键和外键设计
- 分库分表策略
面试重点:
- 数据库三范式
- ACID 特性
- 事务隔离级别和并发问题
- 索引原理和优化
- MySQL InnoDB 和 MyISAM 区别
- MVCC 原理
- 死锁和避免方法
- 慢查询优化
- 主从复制原理
- 分库分表策略
实际应用:
在实际项目中:
- 选择合适的数据库:根据业务需求选择 MySQL 或 PostgreSQL
- 设计合理的表结构:遵循范式,考虑扩展性
- 创建合适的索引:提高查询性能
- 优化慢查询:使用 EXPLAIN 分析,创建索引
- 保证数据一致性:使用事务,设置合适的隔离级别
- 设计高可用架构:主从复制,读写分离,分库分表
参考资料:
- 《高性能 MySQL》
- 《PostgreSQL 即学即用》
- 《数据库系统概念》(Database System Concepts)
- MySQL 官方文档
- PostgreSQL 官方文档