"SELECT 后面接什么来着?"、"加个外键怎么写?"、"怎么查某张表有没有某个字段?"——每次写 SQL 都要掏手机查,查着查着 5 分钟过去了。这份速查手册整理了 MySQL 最常用的命令,从建库建表到查询优化,需要的时候直接 Ctrl+F。
一、库操作
-- 创建数据库
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 查看所有数据库
SHOW DATABASES;
-- 切换数据库
USE mydb;
-- 查看当前所在数据库
SELECT DATABASE();
-- 删除数据库(慎用!)
DROP DATABASE mydb;
为什么用 utf8mb4 而不是 utf8?因为 MySQL 的 utf8 是个阉割版,最多 3 字节,存不了 emoji(😀)。utf8mb4 才是真正的 UTF-8。
二、表操作
-- 创建表
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
age TINYINT UNSIGNED DEFAULT 0,
status ENUM('active', 'inactive', 'banned') DEFAULT 'active',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_email (email),
INDEX idx_status_created (status, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 查看当前库所有表
SHOW TABLES;
-- 查看表结构
DESC users;
SHOW CREATE TABLE users; -- 完整建表语句
-- 查看表的所有索引
SHOW INDEX FROM users;
-- 修改表
ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;
ALTER TABLE users MODIFY COLUMN age SMALLINT UNSIGNED;
ALTER TABLE users DROP COLUMN phone;
ALTER TABLE users RENAME TO customers;
-- 删除表(慎用!)
DROP TABLE users;
三、常用字段类型速查
| 类型 | 用途 | 示例 |
|---|---|---|
INT / BIGINT |
整数 | 用户 ID、数量 |
TINYINT(1) |
布尔值 | is_deleted |
DECIMAL(10,2) |
精确金额 | 99999999.99 |
VARCHAR(N) |
变长字符串 | 用户名、邮箱 |
TEXT |
长文本 | 文章正文 |
LONGTEXT |
超长文本 | Markdown 全文 |
DATETIME |
日期时间 | 2026-07-15 15:30:00 |
TIMESTAMP |
Unix 时间戳 | 自动记录的创建时间 |
ENUM |
固定选项 | 状态字段 |
JSON |
JSON 数据 | 配置、扩展字段 |
选型口诀:钱用 DECIMAL,不长不短用 VARCHAR,要查的就加索引。
四、增删改(CRUD)
-- 插入
INSERT INTO users (username, email, age) VALUES ('john', '[email protected]', 25);
INSERT INTO users (username, email, age) VALUES
('alice', '[email protected]', 30),
('bob', '[email protected]', 28);
-- 查询
SELECT * FROM users;
SELECT id, username, email FROM users WHERE status = 'active';
SELECT * FROM users WHERE age BETWEEN 20 AND 30;
SELECT * FROM users WHERE email LIKE '%@gmail.com';
SELECT DISTINCT status FROM users;
-- 聚合查询
SELECT status, COUNT(*) AS cnt FROM users GROUP BY status;
SELECT status, COUNT(*) AS cnt FROM users GROUP BY status HAVING cnt > 5;
-- 排序和分页
SELECT * FROM users ORDER BY created_at DESC;
SELECT * FROM users LIMIT 10 OFFSET 20; -- 第 3 页,每页 10 条
-- 更新
UPDATE users SET status = 'inactive' WHERE id = 1;
UPDATE users SET age = age + 1 WHERE status = 'active'; -- 活跃用户年龄 +1
-- 删除
DELETE FROM users WHERE id = 1;
DELETE FROM users WHERE created_at < '2025-01-01'; -- 删掉去年的旧数据
-- 软删除(推荐)
UPDATE users SET is_deleted = 1, deleted_at = NOW() WHERE id = 1;
生产环境不要用
DELETE做硬删除,加个is_deleted字段做软删除,后悔药好买。
五、多表查询
-- 内连接(只返回两表都匹配的行)
SELECT u.username, o.order_no, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- 左连接(返回左表全部 + 右表匹配的)
SELECT u.username, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;
-- 子查询
SELECT * FROM users WHERE id IN (
SELECT user_id FROM orders WHERE amount > 1000
);
-- 联合查询(两表结构一样时合并结果)
SELECT username, email FROM users
UNION ALL
SELECT username, email FROM archived_users;
UNION 和 UNION ALL 的区别:UNION 会去重(慢),UNION ALL 不去重(快)。确定不会重复就用 UNION ALL。
六、索引优化(重点)
索引是数据库提速的第一手段,加对索引,查询从扫全表变成直接定位。
-- 创建索引
CREATE INDEX idx_username ON users(username); -- 普通索引
CREATE UNIQUE INDEX idx_email ON users(email); -- 唯一索引
CREATE INDEX idx_status_created ON users(status, created_at); -- 联合索引
-- 查看查询是否用到索引
EXPLAIN SELECT * FROM users WHERE email = '[email protected]';
EXPLAIN 关键字段解读
| 字段 | 好 | 坏 |
|---|---|---|
type |
const, eq_ref, ref, range |
ALL(全表扫描) |
key |
有值(命中索引) | NULL(没用到索引) |
rows |
越小越好 | 几千几万就糟了 |
Extra |
Using index(覆盖索引) |
Using filesort, Using temporary |
索引最佳实践
- 最左前缀原则:联合索引
(A, B, C)能匹配WHERE A、WHERE A AND B,但不能单独匹配WHERE B - 不要在索引列上做计算:
WHERE YEAR(created_at) = 2026不走索引,应改为WHERE created_at BETWEEN '2026-01-01' AND '2026-12-31' - 区分度低的字段别单独建索引:
gender(男女)这种只有两三个值的字段建索引效率极低 - 避免
SELECT *:只查需要的字段,配合覆盖索引效果更好
七、慢查询定位
-- 开启慢查询日志(临时)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 超过 1 秒就算慢查询
-- 查看慢查询日志位置
SHOW VARIABLES LIKE 'slow_query_log_file';
-- 查看当前正在执行的查询
SHOW FULL PROCESSLIST;
-- 杀掉某个卡死的查询
KILL 123; -- 123 是 processlist 里的 Id
慢查询日志是找到性能瓶颈的最直接手段。建议线上环境 long_query_time 设 0.5 秒。
八、备份与恢复
-- 导出单个数据库
mysqldump -u root -p mydb > mydb_backup.sql
-- 导出所有数据库
mysqldump -u root -p --all-databases > all_backup.sql
-- 只导出表结构(不要数据)
mysqldump -u root -p --no-data mydb > schema.sql
-- 恢复
mysql -u root -p mydb < mydb_backup.sql
生产环境一定要定期自动备份,配合 cron 每天凌晨跑一次:
0 3 * * * mysqldump -u root -p'密码' mydb | gzip > /backup/mydb_$(date +\%Y\%m\%d).sql.gz
九、常用运维命令
-- 查看 MySQL 版本
SELECT VERSION();
-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看数据库大小
SELECT table_schema AS '数据库',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS '大小(MB)'
FROM information_schema.tables
GROUP BY table_schema;
-- 查看某张表的大小
SELECT table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS '大小(MB)'
FROM information_schema.tables
WHERE table_schema = 'mydb' AND table_name = 'users';
-- 查看表行数(InnoDB 下是近似值)
SELECT TABLE_ROWS FROM information_schema.tables
WHERE table_schema = 'mydb' AND table_name = 'users';
-- 分析表(更新索引统计信息)
ANALYZE TABLE users;
十、防坑指南
| 坑 | 后果 | 正确做法 |
|---|---|---|
DELETE 不加 WHERE |
全表删除 | 先 SELECT 确认,再改写为 DELETE |
UPDATE 不加 WHERE |
全表更新 | 同上,跑之前必须有 WHERE |
生产环境 DROP |
表没了 | 永远不要对生产直接 DROP |
utf8 而不是 utf8mb4 |
emoji 存不了 | 建库永远用 utf8mb4 |
| 字段无默认值 | 插入报错 | 养成给字段设 DEFAULT 的习惯 |
超大 OFFSET |
翻页越翻越慢 | 用游标分页:WHERE id > 上一页最后一条id LIMIT 10 |
这份手册常用的东西都覆盖了,遇到没列出来的,mysql --help 或者 \h 进 MySQL 敲 help contents 也能查。把这些命令敲熟了,日常开发 95% 的 SQL 场景都够用了。