写 SQL 不是想到什么写什么,而是遵循“库 → 表 → 数据 → 查询 → 优化”的自顶向下设计流。每次开发新功能时,请严格按以下 6 步执行:
明确数据归属,设置正确的字符集(推荐 utf8mb4)。
💡 字符集选错会导致emoji和生僻字存储失败。定义字段类型、主键、非空约束、默认值及注释。
💡 建表时就要想好索引,后期加索引成本更高。录入具有代表性的样本数据,覆盖边界情况。
💡 没有数据的表无法验证查询逻辑是否正确。实现增删改查,先用小数据集验证结果正确性。
💡 UPDATE/DELETE 务必先写 WHERE 再执行!用 EXPLAIN 查看执行计划,确认是否走了预期索引。
💡 不要凭感觉优化,一切以执行计划为准。为应用创建专用账号,最小化权限,禁止root直连。
💡 生产环境永远不要用 root 账号运行应用。WHERE条件 → JOIN关系 → 字段类型 → 索引命中 → 数据本身 逐层排查。
目标:安装 MySQL,掌握最基本的增删改查语句。
-- 创建数据库(指定字符集和排序规则)
CREATE DATABASE IF NOT EXISTS myblog
DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE myblog;
-- 创建用户表
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
email VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0禁用 1正常',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB COMMENT='用户表';
-- 插入
INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com');
-- 查询
SELECT * FROM users WHERE status = 1;
-- 更新(⚠️ 必须带 WHERE)
UPDATE users SET email = 'new@example.com' WHERE username = 'alice';
-- 删除(⚠️ 必须带 WHERE)
DELETE FROM users WHERE username = 'alice';
目标:掌握复杂查询能力,满足日常业务需求。
-- 多条件 + 模糊查询 + 排序 + 分页
SELECT id, username, email, created_at
FROM users
WHERE status = 1
AND username LIKE '%ali%'
ORDER BY created_at DESC
LIMIT 10 OFFSET 0; -- 第1页,每页10条
-- 统计各状态的用户数量
SELECT status, COUNT(*) AS user_count
FROM users
GROUP BY status
HAVING user_count > 5;
| 类别 | 函数 | 用途 |
|---|---|---|
| 字符串 | CONCAT(), SUBSTRING(), LENGTH() | 拼接、截取、长度 |
| 日期 | NOW(), DATE_FORMAT(), DATEDIFF() | 当前时间、格式化、天数差 |
| 条件 | IFNULL(), CASE WHEN | 空值处理、条件分支 |
| 聚合 | COUNT(), SUM(), AVG(), MAX() | 统计分析 |
目标:理解范式与反范式,掌握 JOIN 查询。
-- 文章表(关联用户)
CREATE TABLE articles (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL COMMENT '作者ID',
title VARCHAR(200) NOT NULL,
content TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id), -- ⚡ 外键字段必建索引
CONSTRAINT fk_article_user
FOREIGN KEY (user_id) REFERENCES users(id)
) ENGINE=InnoDB COMMENT='文章表';
-- 查询文章列表及作者名
SELECT a.id, a.title, u.username AS author, a.created_at
FROM articles a
INNER JOIN users u ON a.user_id = u.id
WHERE u.status = 1
ORDER BY a.created_at DESC
LIMIT 20;
目标:理解 B+Tree,会用 EXPLAIN 诊断慢查询。
| 原则 | 说明 | 反面案例 |
|---|---|---|
| 最左前缀 | 联合索引 (a,b,c) 只有查询包含 a 时才生效 | WHERE b=1 AND c=2 ❌ |
| 避免函数运算 | 索引列上做计算会导致索引失效 | WHERE YEAR(created_at)=2024 ❌ |
| 区分度优先 | 将高区分度字段放联合索引左侧 | 性别+身份证号 ❌ |
| 覆盖索引 | SELECT 的字段都在索引中,无需回表 | SELECT * 无法覆盖 ❌ |
EXPLAIN SELECT * FROM articles WHERE user_id = 100;
-- 重点关注以下列:
-- type: ref/range ✅ | ALL ❌(全表扫描)
-- key: 实际使用的索引名(NULL表示未走索引)
-- rows: 预估扫描行数(越小越好)
-- Extra: Using index ✅(覆盖索引) | Using filesort ❌(额外排序)
-- 转账示例:原子性保证
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT; -- 或 ROLLBACK;
-- MySQL默认隔离级别:REPEATABLE READ(可重复读)
-- 解决幻读问题依靠 MVCC + Next-Key Lock
slow_query_log = ON,阈值设为 1s,定期分析优化。| 阶段 | 核心关键词 | 重点掌握内容 |
|---|---|---|
| 基础 | CRUD, DDL | 建库建表, 增删改查, 数据类型 |
| 查询 | JOIN, 聚合, 分页 | 多表关联, GROUP BY, 窗口函数 |
| 设计 | 范式, 外键, ER图 | 三范式, 反范式权衡, 关联设计 |
| 优化 | B+Tree, EXPLAIN | 索引原则, 执行计划, 慢查询分析 |
| 生产 | 事务, 锁, 规范 | ACID, MVCC, 连接池, 安全加固 |