1. SQL(结构化查询语言)

定义:用于管理和操作关系型数据库(如 MySQL、PostgreSQL、SQLite)的标准语言。

主要分类

分类 英文全称 作用 示例
DDL Data Definition Language 定义数据库结构(表、索引、视图) CREATE TABLE, ALTER TABLE, DROP TABLE
DML Data Manipulation Language 操作数据(增、删、改) INSERT, UPDATE, DELETE
DQL Data Query Language 查询数据 SELECT
DCL Data Control Language 权限控制 GRANT, REVOKE

核心查询示例

-- 查询年龄大于 18 岁的用户,按创建时间倒序,只取前 10 条
SELECT id, name, age 
FROM users 
WHERE age > 18 
ORDER BY created_at DESC 
LIMIT 10;

为什么重要
- SQL 是所有关系型数据库的通用语言。
- 即使使用 ORM,理解 SQL 才能排查性能问题、编写复杂查询。


2. 索引

定义:一种用于加速数据检索的数据库结构(类似书的目录)。通常基于 B+ 树或哈希表实现。

工作原理
- 在表的某列(或多列)上创建索引,数据库会维护一个有序的数据结构。
- 查询时,通过索引快速定位到数据行,避免全表扫描(时间复杂度从 O(n) 降到 O(log n))。

类型
- 主键索引(Primary Key):唯一且非空,一张表只能有一个。
- 唯一索引(Unique):列值必须唯一,允许一个 NULL。
- 普通索引(Index):只加速查询,无唯一约束。
- 复合索引(Composite Index):多列组合索引,遵循最左前缀原则。
- 全文索引(Fulltext):用于文本搜索(如 MATCH AGAINST)。

代价
- 占用额外存储空间。
- 增、删、改操作会同步更新索引,降低写入性能。

何时使用索引
- 频繁作为查询条件的列(WHERE, JOIN, ORDER BY, GROUP BY)。
- 区分度高的列(如用户 ID、邮箱),不适合区分度低的列(如性别)。

示例

-- 创建索引
CREATE INDEX idx_user_age ON users(age);

-- 现在执行 SELECT * FROM users WHERE age = 25; 会使用索引

慢查询排查:通过 EXPLAIN 分析是否使用了索引。


3. 事务

定义:一组数据库操作(SQL 语句)被当作一个不可分割的原子单元。要么全部成功,要么全部失败(回滚)。

经典场景:银行转账(A 扣钱、B 加钱,必须同时成功或同时失败)。

ACID 特性

特性 含义 说明
原子性(Atomicity) 事务中的所有操作要么全部完成,要么全部不执行 通过回滚日志(undo log)实现
一致性(Consistency) 事务执行前后,数据库从一个一致状态变到另一个一致状态 由应用层约束 + 数据库约束(外键、唯一)共同保证
隔离性(Isolation) 多个并发事务互不干扰 通过锁机制或 MVCC(多版本并发控制)实现
持久性(Durability) 事务一旦提交,数据永久保存(即使系统崩溃) 通过重做日志(redo log)实现

隔离级别(从低到高,并发性能下降)

隔离级别 脏读 不可重复读 幻读
Read Uncommitted
Read Committed
Repeatable Read ✔(MySQL InnoDB 通过间隙锁避免)
Serializable ✘(完全串行化)
  • 脏读:读到其他事务未提交的数据。
  • 不可重复读:同一事务内两次读同一行,结果不同(因其他事务更新并提交)。
  • 幻读:同一事务内两次范围查询,结果行数不同(因其他事务插入或删除)。

事务控制语句(以 MySQL 为例):

START TRANSACTION;  -- 或 BEGIN
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT;   -- 提交
-- 如果出错则 ROLLBACK;

在代码中使用(伪代码):

try:
    db.begin()
    update_account(1, -100)
    update_account(2, +100)
    db.commit()
except Exception:
    db.rollback()

4. ORM(对象关系映射)

定义:将关系型数据库的表结构映射为编程语言中的对象,让开发者使用面向对象的方式操作数据库,避免手写 SQL。

核心映射
- 表 → 类(Class)
- 行 → 实例(Instance)
- 字段 → 属性(Attribute)
- 外键关联 → 对象引用(关系属性)

流行 ORM 框架
- Python:SQLAlchemy(功能最强大)、Django ORM、Peewee
- Java:Hibernate、MyBatis
- Go:GORM
- JavaScript:Sequelize、TypeORM、Prisma

示例(使用 SQLAlchemy)

# 定义模型
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    age = Column(Integer)

# 查询:User.query.filter(User.age > 18).all()
# 对应的 SQL:SELECT * FROM users WHERE age > 18;

优点
- 提高开发效率,避免拼接 SQL 字符串的错误。
- 自动处理 SQL 注入(通过参数化查询)。
- 数据库迁移方便(如 Alembic)。
- 跨数据库支持(换数据库只需改配置,无需改代码)。

缺点
- 复杂查询(多表 JOIN、聚合、子查询)可能比原生 SQL 难写,且性能不如手写优化 SQL。
- 增加学习成本(需要理解 ORM 的延迟加载、N+1 问题等)。
- 过度依赖可能导致开发者不熟悉 SQL 底层。

常见问题与解决
- N+1 查询:循环查询关联对象 → 使用 joinedloadselectinload 预加载。
- 性能瓶颈:对复杂报表查询,直接写原生 SQL 或使用视图。


概念关联图

SQL(基础语言)
   │
   ├── 索引(优化 SQL 查询速度)
   │
   ├── 事务(保证 SQL 操作的 ACID)
   │
   └── ORM(将 SQL 表映射为对象,自动生成 SQL)

实际工作流
1. 设计数据库表(SQL DDL)。
2. 根据需要创建索引
3. 在应用中通过 ORM 定义模型并操作数据。
4. 当操作需要多个步骤且保证一致性时,使用事务包裹。
5. 遇到性能问题时,查看 ORM 生成的原始 SQL 并用 EXPLAIN 分析索引使用情况。


小结

概念 一句话总结 关键点
SQL 操作关系数据库的标准语言 DDL / DML / DQL,查询优化
索引 加速查询的数据结构 空间换时间,最左前缀原则
事务 保证一组操作原子性 ACID,隔离级别,并发控制
ORM 用对象操作数据库的抽象层 提高效率,但需警惕 N+1 和复杂查询