MySQL 冷门实用语法合集(下篇):索引、锁、虚拟列、调试工具进阶用法

0 阅读5分钟

前言

上篇我们介绍了数据写入、分组、内置函数相关的冷门语法,本篇聚焦性能优化、并发控制、动态字段、SQL 调试四大进阶方向。这些语法日常使用频率不高,但在 SQL 调优、并发场景、复杂计算、问题排查时能起到关键作用,是中高级后端开发必备知识点。

一、虚拟列(VIRTUAL / STORED)动态计算字段

MySQL 5.7+ 支持生成列(虚拟列) ,字段值由其他字段计算得出,无需 Java 代码手动计算,还支持建立索引,兼顾便捷性与查询性能。分为两种类型:

  1. VIRTUAL(默认):不物理存储数据,查询时实时计算,不占用磁盘空间;
  2. STORED:物理存储数据,写入 / 更新数据时计算,占用磁盘空间。

示例

sql

-- 订单明细表:单价 * 数量 自动计算总价
CREATE TABLE `order_item` (
  id INT PRIMARY KEY AUTO_INCREMENT,
  price DECIMAL(10,2) COMMENT '单价',
  num INT COMMENT '数量',
  -- 虚拟列:查询时自动计算,无物理存储
  total_price DECIMAL(10,2) GENERATED ALWAYS AS (price * num) VIRTUAL
) COMMENT '订单明细';

-- 正常插入数据,无需赋值 total_price
INSERT INTO `order_item` (price, num) VALUES (99.9, 2);

-- 直接查询计算后的总价
SELECT * FROM `order_item`;

进阶:给虚拟列建索引

虚拟列支持索引,适合高频筛选计算后字段的场景:

sql

CREATE INDEX idx_total_price ON order_item(total_price);

适用场景

金额计算、比例换算、状态衍生字段、拼接字段;

避坑

虚拟列不支持手动 INSERT/UPDATE 赋值,数值完全依赖计算表达式。

二、索引干预:FORCE INDEX / IGNORE INDEX

MySQL 优化器有时会选错索引(例如小表走全表扫描、优先使用低效索引),这时可以手动干预索引选择,强制使用 / 忽略指定索引。

1. FORCE INDEX 强制使用索引

sql

-- 强制使用 idx_name 索引查询
SELECT * FROM `sys_user` 
FORCE INDEX (idx_name) 
WHERE name = '张三';

2. IGNORE INDEX 忽略指定索引

sql

-- 忽略 idx_age 索引,让数据库自行选择最优方案
SELECT * FROM `sys_user` 
IGNORE INDEX (idx_age) 
WHERE age > 20;

适用场景

SQL 调优、优化器索引选择异常、复杂联表查询索引错乱;

避坑

仅作为临时调优手段,不建议在业务代码中长期使用,优先通过优化 SQL、统计信息解决索引问题。

三、并发控制:SELECT ... FOR UPDATE 行级悲观锁

在事务中,使用 FOR UPDATE 可以对查询到的行加行级排他锁,防止多事务并发修改数据,实现简单的悲观锁控制。锁生效范围:当前事务未提交前,其他事务无法更新 / 删除该行,普通查询不受影响。

示例

sql

-- 开启事务
BEGIN;

-- 锁定 id=1 的行,其他事务阻塞更新操作
SELECT * FROM `sys_user` WHERE id = 1 FOR UPDATE;

-- 执行业务更新逻辑
UPDATE `sys_user` SET age = 30 WHERE id = 1;

-- 提交事务,锁释放
COMMIT;

适用场景

库存扣减、金额变动、订单状态修改等强并发写场景;

避坑

  1. 锁仅在事务内生效;
  2. 查询条件必须命中索引,否则会升级为表锁;
  3. 控制事务执行时长,避免长事务导致锁等待。

四、SQL 调试:EXPLAIN ANALYZE 真实执行计划

传统 EXPLAIN 仅为预估执行计划,数据是 MySQL 优化器推算结果。MySQL 8.0.18+ 推出 EXPLAIN ANALYZE真实执行 SQL,返回实际耗时、扫描行数、循环次数,是 SQL 调优神器。

示例

sql

-- 真实执行SQL,输出详细运行指标
EXPLAIN ANALYZE 
SELECT * FROM `sys_user` WHERE dept_id = 1;

关键字段解读

  • actual time:真实执行耗时;
  • rows:实际扫描 / 返回行数;
  • Table scan:全表扫描(优化重点)。

适用场景

慢 SQL 排查、索引验证、复杂联表 SQL 性能分析。

五、交互式语法:HELP 内置帮助命令

不用翻阅官方文档,直接在 MySQL 客户端内查询语法、函数、关键字的官方说明,临时查用法非常方便。

示例

sql

-- 查询 SELECT 语法说明
HELP SELECT;

-- 查询索引相关语法
HELP INDEX;

-- 查询日期格式化函数用法
HELP DATE_FORMAT;

适用场景

线上服务器临时查语法、函数用法、忘记参数时快速检索。

六、REPLACE INTO 覆盖写入

REPLACE INTO 是一种特殊的写入语法:当主键 / 唯一索引冲突时,先删除原有数据,再插入新数据,区别于 ON DUPLICATE KEY UPDATE 的原地更新。

示例

sql

-- id 为主键,重复数据会先删后插
REPLACE INTO `sys_user` (id, name, age) VALUES (1, '王五', 29);

和 ON DUPLICATE KEY UPDATE 区别

  1. REPLACE INTO:删旧数据 + 插新数据,自增 ID 会变化、触发器会多次触发;
  2. ON DUPLICATE KEY UPDATE:原地更新字段,数据行不变。

避坑

谨慎使用在主业务表,删除操作会影响关联数据、日志、触发器。

适用场景

临时配置表、缓存数据覆盖、简单数据重置。

总结

本篇语法偏向进阶优化与并发控制,侧重点和上篇形成互补:

  1. 虚拟列:将计算逻辑下沉到数据库,简化代码;
  2. 索引干预:临时解决优化器选错索引的问题;
  3. 行锁:实现简单悲观锁,应对并发更新;
  4. 执行计划 + 帮助命令:提升问题排查、学习效率;
  5. REPLACE INTO:特殊场景的数据覆盖写入。