MySQL的10种高级SQL,性能飞升

MySQL 的 10 种高级 SQL 技巧,性能飞升(2026 年最新实战版)

以下 10 条是 2025–2026 年 MySQL(8.0/8.4/9.x 系列)生产环境中最常用来提速 5–50 倍的高级写法和优化思路,按实用频度从高到低排序。每条都带真实场景优化前后对比关键注意点

1. 覆盖索引 + 强制索引顺序(covering index + index hint)

-- 优化前(回表 2 次)
SELECT id, name, create_time FROM users WHERE status=1 ORDER BY create_time DESC LIMIT 10;

-- 优化后(单次索引覆盖,无回表)
CREATE INDEX idx_status_create ON users(status, create_time, id, name);

SELECT id, name, create_time 
FROM users FORCE INDEX(idx_status_create)
WHERE status=1 
ORDER BY create_time DESC LIMIT 10;

提速倍数:3–20 倍(大表常见)
适用:分页列表、排行榜、feed 流
2026 新提示:MySQL 8.4+ 对覆盖索引排序的代价估算更准,FORCE INDEX 胜率更高。

2. 延迟物化 + 子查询转 JOIN(late materialization)

-- 优化前(全表扫 + 子查询)
SELECT * FROM orders 
WHERE user_id IN (SELECT user_id FROM users WHERE vip_level >= 3);

-- 优化后(先取少量 id 再 join)
SELECT o.* 
FROM orders o
INNER JOIN (
    SELECT user_id FROM users WHERE vip_level >= 3 LIMIT 5000
) t ON o.user_id = t.user_id;

提速倍数:5–30 倍(子查询结果集小时特别明显)
适用:IN 子查询结果集 < 1% 总行数时

3. 索引条件下推(Index Condition Pushdown)+ 函数索引

-- 8.0 前必须建 (LEFT(phone,7))
CREATE INDEX idx_phone_prefix ON users ((LEFT(phone,7)));

-- 现在直接用函数索引(MySQL 8.0+)
SELECT * FROM users 
WHERE LEFT(phone,7) = '1381234';

额外加分JSON_EXTRACTJSON_VALUE 也能建函数索引(8.0.21+)

4. 批量 + ON DUPLICATE KEY UPDATE(upsert 批量插入)

INSERT INTO user_stats (user_id, views, likes, updated_at)
VALUES 
    (1001, 5, 2, NOW()),
    (1002, 3, 1, NOW()),
    (1003, 7, 0, NOW())
ON DUPLICATE KEY UPDATE 
    views = views + VALUES(views),
    likes = likes + VALUES(likes),
    updated_at = VALUES(updated_at);

提速倍数:10–100 倍(对比单条 update/insert)
适用:实时埋点统计、UV/PV 计数、排行榜增量更新

5. 巧用窗口函数替代自连接 / 子查询(Window Function)

-- 优化前(自连接)
SELECT t1.id, t1.score, COUNT(*) rank
FROM scores t1
JOIN scores t2 ON t2.score >= t1.score
GROUP BY t1.id;

-- 优化后(窗口函数,MySQL 8.0+)
SELECT id, score,
       DENSE_RANK() OVER (ORDER BY score DESC) AS `rank`
FROM scores;

提速倍数:5–40 倍(分组排名、去重、累计求和场景)

6. 避免大分页(深分页优化)—— 使用覆盖 + 延迟

-- 坏写法(扫描 100000 行再丢弃前 99990 行)
SELECT * FROM logs ORDER BY id DESC LIMIT 99990, 10;

-- 好写法(记住上一页最后 id)
SELECT * FROM logs 
WHERE id < 最后一条id 
ORDER BY id DESC LIMIT 10;

极致写法(结合覆盖索引):

SELECT id FROM logs FORCE INDEX(idx_create_time) 
WHERE create_time < '最后时间' 
ORDER BY create_time DESC LIMIT 10;

提速倍数:几十到几百倍(page=10000+ 时)

7. 强制索引 + 索引合并(Index Merge)控制

-- 让优化器选择 union 索引而非全扫
SELECT * FROM orders FORCE INDEX(idx_status, idx_create)
WHERE (status=1 OR status=2) AND create_time > '2025-01-01';

2026 小技巧USE INDEX FOR ORDER BY / FOR GROUP BY 单独控制排序/分组索引

8. 聚合查询下推 + HAVING 提前过滤

-- 优化前
SELECT user_id, COUNT(*) cnt 
FROM events 
GROUP BY user_id 
HAVING cnt > 100;

-- 优化后(where 先过滤)
SELECT user_id, COUNT(*) cnt 
FROM events 
WHERE event_type IN ('login','pay')   -- 假设只统计这两种
GROUP BY user_id 
HAVING cnt > 100;

提速倍数:2–15 倍(聚合前数据量减少明显)

9. 利用直方图 + 持久化统计信息(MySQL 8.0+)

-- 提升不等值/范围查询准确度
ANALYZE TABLE users UPDATE HISTOGRAM ON age WITH 256 BUCKETS;
ANALYZE TABLE orders PERSISTENT FOR COLUMNS (status, create_time);

效果:IN 子句、BETWEEN、> < 条件下的基数估计更准,执行计划崩的概率大幅降低

10. CTE + 可物化 CTE(MySQL 8.0+ / 8.4 增强)

WITH RECURSIVE date_range AS (
    SELECT DATE('2025-01-01') AS dt
    UNION ALL
    SELECT dt + INTERVAL 1 DAY FROM date_range WHERE dt < '2025-12-31'
),
daily_stats AS (
    SELECT /*+ MATERIALIZED */   -- 8.4+ 强制物化,避免重复计算
        dt, COUNT(*) orders
    FROM date_range
    LEFT JOIN orders o ON DATE(o.create_time) = dt
    GROUP BY dt
)
SELECT * FROM daily_stats ORDER BY dt;

提速倍数:3–20 倍(复杂报表、连续日期补 0、树形递归)

快速对照表(2026 年最值钱 10 条)

排名技巧典型提速倍数难度出现频率
1覆盖索引 + FORCE INDEX3–20×★★☆★★★★★
2延迟物化子查询5–30×★★★★★★★☆
3函数索引 / JSON索引5–50×★★☆★★★★☆
4INSERT … ON DUPLICATE10–100×★☆☆★★★★★
5窗口函数替换自连接5–40×★★★★★★★☆
6深分页 → 游标式10–500×★★☆★★★★★
7Index Merge 控制2–15×★★★★★★☆☆
8聚合前 where 下推2–15×★★☆★★★★☆
9直方图 + 持久化统计2–10×(防崩)★★☆★★★★☆
10可物化 CTE3–20×★★★★★★★☆☆

你目前项目里最痛的慢 SQL 是哪种类型?
(分页深?JOIN 多?GROUP BY 慢?范围扫描?实时统计?子查询爆炸?)

告诉我表结构 + 慢查询原文,我可以直接帮你改出高性能版本。

文章已创建 4791

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部