MySQL 增删改查详解

增删改查是数据库操作的基础,但不同层次的理解深度决定了 SQL 编写的质量和效率。本文以层次递进的方式,从最基础的语法,到执行逻辑、性能优化,再到高级注意事项,系统梳理 MySQL 中的 CRUD 核心知识。

一、基础操作

1.1 INSERT:插入数据

sql 复制代码
-- 单行插入
INSERT INTO users (name, age) VALUES ('Alice', 25);

-- 多行插入
INSERT INTO users (name, age) VALUES ('Bob', 30), ('Carol', 28);

-- 插入查询结果
INSERT INTO archive_users SELECT * FROM users WHERE age > 60;

1.2 SELECT:查询数据

sql 复制代码
-- 基本查询
SELECT name, age FROM users WHERE age > 18;

-- 排序与分页
SELECT * FROM users ORDER BY age DESC LIMIT 10, 20; -- 跳过10条取20条

-- 聚合与分组
SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) > 5000;

1.3 UPDATE:更新数据

sql 复制代码
-- 更新单行/多行
UPDATE users SET age = 26 WHERE name = 'Alice';

-- 批量更新(谨慎使用)
UPDATE users SET status = 1 WHERE age > 60;

1.4 DELETE:删除数据

sql 复制代码
-- 条件删除
DELETE FROM users WHERE id = 123;

-- 清空全表
TRUNCATE TABLE temp_logs;

二、执行逻辑

2.1 SELECT 的逻辑执行顺序

书写顺序 ≠ 执行顺序。数据库引擎按以下顺序处理:

  1. FROM:确定表及连接方式
  2. WHERE:逐行过滤
  3. GROUP BY:分组
  4. HAVING:过滤分组
  5. SELECT:选择列、计算表达式
  6. ORDER BY:排序
  7. LIMIT:截取行数

这个顺序解释了为什么 WHERE 不能用 SELECT 中的别名,而 ORDER BY 可以。例如:

sql 复制代码
-- 错误:WHERE 无法识别别名 total
SELECT salary * 12 AS total FROM emp WHERE total > 100000;
-- 正确:使用表达式或子查询
SELECT salary * 12 AS total FROM emp WHERE salary * 12 > 100000;

2.2 索引如何影响 CRUD

  • SELECT :索引加速 WHEREJOINORDER BYGROUP BY,且覆盖索引可避免回表。
  • INSERT/UPDATE/DELETE:索引虽加速条件定位,但会带来维护成本。每次修改索引列都需要同步更新索引结构。

2.3 事务与锁

在 InnoDB 中:

  • SELECT 默认不加锁(快照读),除非使用 FOR UPDATELOCK IN SHARE MODE
  • INSERT 产生插入意向锁,通常不阻塞其他插入。
  • UPDATE/DELETE 对匹配行加排他锁,并可能加间隙锁,范围越大锁越多。

三、性能与优化

3.1 插入优化

  • 批量插入INSERT INTO ... VALUES (...), (...) 比逐条插入快数倍。
  • 关闭自动提交:将多条插入包在一个事务中,减少磁盘同步。
  • 使用 LOAD DATA INFILE:适合大批量文本导入,效率最高。

3.2 查询优化

  • 避免 SELECT *:只取需要的列,减少网络传输和内存开销。
  • 索引列上避免函数或运算WHERE YEAR(create_time) = 2023 无法走索引,应改为范围查询。
  • 联合索引最左前缀 :索引 (a, b, c) 支持 aa,ba,b,c 的查询,不支持跳过 a 使用 b
  • 覆盖索引 :查询的列都包含在索引中,无需回表,EXPLAIN 显示 Using index

3.3 更新与删除优化

  • 使用索引定位WHERE 条件列有索引时,更新/删除只锁定少量行,否则可能锁全表。
  • 分批操作:大范围更新/删除应拆分成多批,每批处理几千行,减少长事务和锁持有时间。
  • 注意碎片 :频繁 DELETE 后表空间不会释放,可定期 OPTIMIZE TABLE 整理碎片(低峰期执行)。

四、注意事项

4.1 INSERT 的主键冲突处理

  • INSERT IGNORE:跳过冲突行,适合批量导入时忽略重复。

  • ON DUPLICATE KEY UPDATE:存在则更新,不存在则插入,常用于幂等写入。

    sql 复制代码
    INSERT INTO daily_stats (date, pv) VALUES ('2023-01-01', 100)
    ON DUPLICATE KEY UPDATE pv = pv + VALUES(pv);

4.2 UPDATE 与 DELETE 的"危险"设计

  • 不带 WHERE 会作用于全表,这是 SQL 语法允许的,但极易误操作。建议在开发环境开启 sql_safe_updates 模式,禁止无条件的更新删除。
  • DELETE 不会重置自增计数器,TRUNCATE 会。

4.3 锁与死锁

  • 更新/删除时,如果多个事务以不同顺序锁定多行,可能发生死锁。优化方式:尽量按相同顺序操作,缩短事务,合理设计索引减少锁范围。
  • 间隙锁可能导致并发插入阻塞,在 REPEATABLE READ 下尤其明显。评估业务是否需要使用 READ COMMITTED 隔离级别。

4.4 大数据量下的特殊手段

  • 归档旧数据:定期将历史数据移出主表,减小主表体积。
  • 分区表:按时间等维度分区,便于快速删除整个分区(TRUNCATE PARTITION)。
  • 异步批量删除:通过程序分批循环删除,避免长事务。

总结

掌握增删改查的层次结构:

  • 基础层:能写出正确的 SQL。
  • 逻辑层:理解语句执行顺序、索引和锁的影响。
  • 优化层:针对性能瓶颈进行优化。
  • 高级层:应对复杂场景和工程陷阱。
相关推荐
Sagittarius_A*1 小时前
【LitCTF2026】lit_ezsql
android·java·数据库
未秃头的程序猿2 小时前
分库分表一年后,我复盘了当时最该想清楚的三件事
java·数据库·后端
心易行者2 小时前
用html在线运行做数据可视化大屏,5个实战场景从入门到上线
大数据·前端·数据库·人工智能·python
꯭自꯭闭꯭2 小时前
达梦(DM8)安装测试
linux·运维·服务器·数据库
袁因2 小时前
Oracle 慢 SQL 优化:Cost 最高的那行不是瓶颈,真凶藏在 SELECT 列表里
数据库
天衍四九-3 小时前
Agent Skills从入门到工程化(十六):面试中如何讲清楚 Agent Skills?
大数据·数据库·人工智能·python·chatgpt·面试
H_oRIZoN_3 小时前
Linux入门DAY37(IO 多路复用、TCP 并发服务器与数据库 SQLite3 详解)
linux·服务器·数据库
2501_930472443 小时前
05_数据库迁移腾讯云_DTS评估与预检回滚清单
数据库·云计算·腾讯云