MySQL 8.0 新特性

面试官问:"你用过 MySQL 8.0 吗?有哪些新特性?"

小陈说:"8.0 更快?"

面试官追问:"有了解过窗口函数吗?"

小陈说:"...像 GROUP BY 那样分组?"

面试官继续追问:"那你知道 ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 怎么用吗?"

小陈彻底卡住了。

MySQL 8.0 是 MySQL 史上最重要的版本升级之一。窗口函数、CTE、Hash Join 等特性让 MySQL 的 SQL 能力大幅提升。知道这些新特性的候选人,说明他对 MySQL 有持续关注,而不是固守 5.7 时代的技术栈。

一、窗口函数(Window Functions)🔴

1.1 什么是窗口函数

窗口函数在一组行上执行聚合/排名操作,但不减少行数——每行仍然保留,只是多了一列计算结果。

-- 传统聚合:减少行数
SELECT user_id, SUM(amount) FROM orders GROUP BY user_id;
-- 结果:每个用户一行

-- 窗口函数:不减少行数
SELECT
    order_no,
    user_id,
    amount,
    SUM(amount) OVER (PARTITION BY user_id) as user_total
FROM orders;
-- 结果:每行都有,同时返回该用户的总金额

1.2 常见窗口函数

类型函数说明
排名ROW_NUMBER()1, 2, 3, 4(无并列)
排名RANK()1, 1, 3, 4(有并列,跳号)
排名DENSE_RANK()1, 1, 2, 3(有并列,不跳号)
聚合SUM/AVG/COUNT/MAX/MIN在窗口内聚合
前后LAG()/LEAD()取前一行/后一行的值
首尾FIRST_VALUE()/LAST_VALUE()取窗口首尾值

1.3 典型场景

-- 场景 1:按用户查订单,同时计算累计金额
SELECT
    order_no,
    created_at,
    amount,
    SUM(amount) OVER (
        PARTITION BY user_id
        ORDER BY created_at
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) as cumulative_amount
FROM orders;

-- 场景 2:查每个用户的订单排名
SELECT
    order_no,
    amount,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY amount DESC) as rank
FROM orders;

-- 场景 3:查环比增长
SELECT
    month,
    revenue,
    LAG(revenue) OVER (ORDER BY month) as prev_month_revenue,
    revenue - LAG(revenue) OVER (ORDER BY month) as growth
FROM monthly_sales;

1.4 ❌ 错误示范

候选人原话:"窗口函数就是 GROUP BY,只是写法不一样。"

问题诊断:GROUP BY 减少行数,窗口函数不减少行数。两者有本质区别。

候选人原话 2:"MySQL 5.7 也有窗口函数。"

问题诊断:窗口函数是 MySQL 8.0 才引入的特性。5.7 不支持。

【面试官心理】 窗口函数是 MySQL 8.0 最实用的新特性。能说出窗口函数的实际应用场景(如排名、累计、环比)的候选人,说明他不只是看了新特性介绍,而是真正用过。

二、通用表表达式(CTE)🔴

2.1 递归 CTE

-- 递归查询:查询组织架构
WITH RECURSIVE org_tree AS (
    -- 基础查询:CEO
    SELECT id, name, manager_id, 1 as level
    FROM employees
    WHERE manager_id IS NULL

    UNION ALL

    -- 递归查询:下属
    SELECT e.id, e.name, e.manager_id, ot.level + 1
    FROM employees e
    JOIN org_tree ot ON e.manager_id = ot.id
)
SELECT * FROM org_tree;

-- 替代方案:多层嵌套子查询(难读、难维护)

2.2 非递归 CTE

-- 普通 CTE:替代嵌套子查询
WITH active_users AS (
    SELECT id, name FROM users WHERE status = 1
),
recent_orders AS (
    SELECT * FROM orders WHERE created_at >= '2024-01-01'
)
SELECT u.name, COUNT(o.id) as order_count
FROM active_users u
LEFT JOIN recent_orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

三、Hash Join 🟡

3.1 MySQL 8.0 的 Hash Join

-- MySQL 8.0 支持 Hash Join
SELECT * FROM orders o
JOIN users u ON o.user_id = u.id;

-- 执行计划显示:
-- "Nested loop hash join"

3.2 Hash Join vs NLJ

场景NLJHash Join
被驱动表有索引✅ 高效一般
被驱动表无索引❌ 差✅ 高效
大表 JOIN 大表❌ 差✅ 可行
内存不足-退化为磁盘

四、其他重要特性 🟡

4.1 JSON 函数增强

-- JSON_TABLE:把 JSON 转为表
SELECT *
FROM JSON_TABLE(
    '[{"name":"Tom","age":25}, {"name":"Jerry","age":30}]',
    '$[*]' COLUMNS (
        name VARCHAR(50) PATH '$.name',
        age INT PATH '$.age'
    )
) as t;

-- JSON_VALUE:提取 JSON 字段值
SELECT JSON_VALUE(extra, '$.phone') as phone FROM users;

4.2 窗口函数 + CTE 组合

-- 查每个月的销售额,以及环比增长率
WITH monthly AS (
    SELECT
        DATE_FORMAT(created_at, '%Y-%m') as month,
        SUM(amount) as revenue
    FROM orders
    GROUP BY DATE_FORMAT(created_at, '%Y-%m')
)
SELECT
    month,
    revenue,
    LAG(revenue) OVER (ORDER BY month) as prev_revenue,
    ROUND(
        (revenue - LAG(revenue) OVER (ORDER BY month)) /
        LAG(revenue) OVER (ORDER BY month) * 100, 2
    ) as growth_rate
FROM monthly
ORDER BY month;

4.3 GIS 增强

-- MySQL 8.0 支持 Spatial Reference ID (SRID)
-- 支持更精确的地理计算
SELECT ST_Distance_Sphere(
    ST_GeomFromText('POINT(116.4074 39.9042)', 4326),  -- 北京
    ST_GeomFromText('POINT(121.4737 31.2304)', 4326)   -- 上海
) as distance_meters;

【面试官心理】 MySQL 8.0 新特性是 MySQL 面试中的加分项。能说清楚窗口函数和 CTE 实际用法的候选人,说明他对 SQL 有深入实践,不只是CRUD 工程师。


级别考察重点期望回答
P5知道新特性窗口函数、CTE、Hash Join 名称
P6理解用法窗口函数语法、典型场景
P7深度应用递归 CTE、窗口函数 + CTE 组合