7 个 MySQL 高级用法

袁志蒙 102次浏览

摘要:你还在使用循环 + 单条 SQL 处理业务数据?本文总结7 个 MySQL 生产环境实用高级语法,涵盖关联更新、关联删除、存在即更新、批量操作、查询优化等高阶写法,告别低效循环,让数据库操作性能提升 10~100 倍...

很多开发者长期停留在基础增删改查 + 循环操作的阶段,不仅代码冗余、性能低下,遇到大数据量还容易造成锁表、接口超时。

今天给大家总结7 个生产环境最实用、最高效的 MySQL 高级写法,学会就能直接替代 90% 的循环操作,性能提升 10~100 倍,不管是做 IM 聊天、订单系统、后台管理都能直接用。

前言

日常开发中,我们经常遇到这类需求:

批量更新关联表数据

批量删除关联数据

存在则更新、不存在则插入

批量条件修改不同数据

防止大批量更新锁表

传统 PHP 写法:先查询→循环→单条执行 SQL,网络开销大、性能极差、高并发下极易出问题。

而 MySQL 原生支持的高级语法,能让我们用一条 SQL完成所有操作,这才是后端开发的正确姿势。

一、UPDATE JOIN:关联表批量更新(神技)

作用:根据另一张表的数据条件,批量更新当前表,无需循环、无需冗余字段。

适用场景

聊天记录批量标记删除 / 已读

订单状态关联商品库存同步

用户信息同步更新关联表

语法:

UPDATE 表A
JOIN 表B ON 表A.关联字段 = 表B.关联字段
SET 表A.字段 = 新值
WHERE 筛选条件;

实战案例(聊天记录删除)

-- 用户删除一年前的聊天记录(状态表标记删除)
UPDATE chat_message_status s
INNER JOIN chat_messages m ON s.message_id = m.id
SET 
  s.is_deleted = 1,
  s.delete_time = UNIX_TIMESTAMP()
WHERE 
  s.user_id = 1
  AND s.is_deleted = 0
  AND m.create_time <= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 YEAR));

优点

一条 SQL 完成联表操作

性能远超 PHP 循环更新

无需给状态表加冗余时间字段

二、DELETE JOIN:关联表批量删除

作用:根据关联表条件,直接删除主表数据,不用先查 ID 再删除。

适用场景

删除用户时,清理所有关联消息 / 日志

清理过期订单及关联详情

语法

DELETE 要删除的表别名
FROM 主表
JOIN 关联表 ON 关联条件
WHERE 筛选条件;

实战案例

-- 删除用户1一年前的所有聊天状态数据
DELETE s
FROM chat_message_status s
JOIN chat_messages m ON s.message_id = m.id
WHERE 
  s.user_id = 1 
  AND m.create_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 YEAR));

三、INSERT ... ON DUPLICATE KEY UPDATE:存在更新,不存在插入(最常用)

作用:数据不存在就插入,存在就更新,原子操作,无重复插入风险。

前提

表必须有主键 / 唯一索引,冲突时触发更新。

适用场景

聊天消息已读状态记录

用户签到、统计计数

配置信息保存

实战案例(聊天已读状态)

-- 消息已读:存在则更新已读状态,不存在则新增
INSERT INTO chat_message_status (message_id, user_id, is_read, read_time)
VALUES (1001, 10, 1, UNIX_TIMESTAMP())
ON DUPLICATE KEY UPDATE 
  is_read = 1,
  read_time = UNIX_TIMESTAMP();

优点

  • 替代「先查询、再判断、再插入 / 更新」的冗余代码

  • 高并发下不重复插入

  • 性能比 PHP 逻辑处理快数倍

四、CASE WHEN:批量条件更新

作用:一条 SQL 批量更新不同数据,不用写多条 UPDATE 语句。

适用场景

批量修改不同订单的状态

批量设置不同消息的已读 / 删除状态

批量更新用户等级

语法

UPDATE 表
SET 字段 = CASE 条件字段
  WHEN 值1 THEN 新值1
  WHEN 值2 THEN 新值2
END
WHERE 范围条件;

实战案例

-- 批量设置消息已读状态:id=1已读,id=2未读
UPDATE chat_message_status
SET is_read = CASE id
  WHEN 1 THEN 1
  WHEN 2 THEN 0
END
WHERE id IN (1,2);

五、JOIN 替代子查询:查询性能翻倍

问题:MySQL 对子查询优化较差,大数据量下子查询会全表扫描,速度极慢。

优化方案:用 JOIN 关联查询 替代子查询,性能提升 10 倍以上。

反例(慢)

-- 子查询写法
SELECT * FROM chat_message_status
WHERE message_id IN (SELECT id FROM chat_messages WHERE create_time < 1704067200);

正例(快)

-- JOIN关联写法
SELECT s.* FROM chat_message_status s
JOIN chat_messages m ON s.message_id = m.id
WHERE m.create_time < 1704067200;

六、LIMIT 分批更新 / 删除:防止锁表卡死

作用:大批量数据更新时,一次只处理少量数据,避免长事务锁表,导致业务卡顿。

适用场景

清理历史日志

批量标记过期数据

千万级数据处理

实战案例

-- 每次只更新1000条,PHP循环执行直到完成
UPDATE chat_message_status s
JOIN chat_messages m ON s.message_id = m.id
SET s.is_deleted = 1
WHERE 
  s.user_id = 1 
  AND m.create_time < 1704067200
LIMIT 1000;

生产环境必备

所有大批量更新操作,必须加 LIMIT 分批处理!

七、REPLACE INTO:覆盖写入数据

作用:存在则删除旧数据,插入新数据;不存在则直接插入。

注意

会删除原数据并重写,自增 ID 会发生变化。

适用场景

简单覆盖式配置保存

无需保留历史 ID 的场景

语法

REPLACE INTO 表 (字段1,字段2) VALUES (值1,值2);

总结:7 大技能速查表

语法核心用途必备场景
UPDATE JOIN关联表批量更新聊天状态、订单同步
DELETE JOIN关联表批量删除清理关联数据
INSERT ... ON DUPLICATE存在更新 / 不存在插入已读状态、签到、计数
CASE WHEN批量条件更新批量修改不同数据
JOIN 替代子查询提升查询速度所有关联查询
LIMIT 分批处理防锁表、防卡死大批量数据操作
REPLACE INTO覆盖写入简单覆盖保存


随机内容

表情

共0条评论
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~