系统对比 MySQL 8.0.46 与 MySQL 9.7.0 ,并结合 Java 场景给出可运行的示例说明。
(不涉及 JDBC 驱动、连接方式等前置内容,只谈 SQL 本身)
一、总体结论先行(SQL 层面)
| 对比维度 | MySQL 8.0.46 | MySQL 9.7.0 |
|---|---|---|
| JSON Duality View | ❌ 不支持 | ✅ 支持(可 DML) |
| EXPLAIN 优化器 | 传统 CBO | ✅ Hypergraph |
| 查询改写 | 有限 | ✅ 更强 |
| SQL 语法扩展 | 较少 | ✅ 明显增多 |
| 递归 / 分析函数 | 基本支持 | ✅ 更稳定 |
| 参数化 SQL 行为 | 部分差异 | ✅ 更严格 |
**一句话总结:**
MySQL 9.7.0 在 SQL 层面最大的变化是------
"能用更少的 SQL,完成更复杂的数据建模与查询。"
二、JSON Duality Views(最核心差异)
1️⃣ MySQL 8.0.46 的局限
在 8.0 中,如果你想用 JSON:
-
只能用
JSON_OBJECT -
只能
SELECT -
不能直接
INSERT / UPDATE
示例(MySQL 8.0)
-- 普通 JSON 查询
SELECT
JSON_OBJECT(
'id', o.id,
'customer', o.customer_name
) AS order_json
FROM orders o;
👉 问题:
-
Java 中需要自己拆 JSON
-
无法直接反向写回数据库
-
复杂 JSON = 大量 SQL
2️⃣ MySQL 9.7.0:JSON Duality View(革命性)
定义 Duality View
CREATE OR REPLACE VIEW order_jv OF JSON WITH DATA AS
SELECT JSON_OBJECT(
'orderId' : o.id,
'customer' : o.customer_name,
'items' : (
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'product' : i.product,
'qty' : i.quantity
)
)
FROM order_items i
WHERE i.order_id = o.id
)
)
FROM orders o;
✅ 这是 9.7 独有的 SQL 能力
Java 中直接操作 JSON(9.7)
String sql = "INSERT INTO order_jv VALUES (?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, """
{
"orderId": 9001,
"customer": "Tom",
"items": [
{ "product": "Mouse", "qty": 2 }
]
}
""");
ps.executeUpdate();
✅ 不需要:
-
拆分表
-
多表 INSERT
-
MyBatis / JPA 映射
UPDATE(9.7 支持)
UPDATE order_jv
SET data = JSON_SET(data, '$.customer', 'Jerry')
WHERE data->>'$.orderId' = '9001';
📌 在 8.0 中这是不可能的
三、EXPLAIN 与优化器差异(SQL 行为变化)
1️⃣ MySQL 8.0.46
EXPLAIN
SELECT *
FROM orders o
JOIN order_items i ON o.id = i.order_id
WHERE o.status = 'PAID';
输出:
-
传统 Join Order
-
通常左深树
-
优化器选择有限
2️⃣ MySQL 9.7.0(Hypergraph)
EXPLAIN FORMAT=JSON
SELECT *
FROM orders o
JOIN order_items i ON o.id = i.order_id
WHERE o.status = 'PAID';
✅ 特点:
-
支持 Bushy Join
-
多表 JOIN 顺序更优
-
复杂 SQL 自动重写
📌 对 Java 的影响:
-
同一条 SQL
-
在 9.7 可能快 30%~200%
四、WITH / CTE 的差异
1️⃣ MySQL 8.0.46
WITH cte AS (
SELECT order_id, SUM(amount) s
FROM payments
GROUP BY order_id
)
SELECT * FROM cte WHERE s > 1000;
✅ 支持
❌ 优化器能力较弱
2️⃣ MySQL 9.7.0
WITH RECURSIVE tree AS (
SELECT id, parent_id, name
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.parent_id, c.name
FROM categories c
JOIN tree t ON c.parent_id = t.id
)
SELECT * FROM tree;
✅ 递归更稳定
✅ 执行计划更优
✅ Java 中适合菜单 / 组织结构
五、GROUP BY / DISTINCT 行为更严格
MySQL 8.0
SELECT status, COUNT(*)
FROM orders
GROUP BY status
ORDER BY create_time;
⚠️ 可能不报错(非标准 SQL)
MySQL 9.7.0(更严格)
SELECT status, COUNT(*), create_time
FROM orders
GROUP BY status;
❌ 直接报错:
Expression #3 of SELECT list is not in GROUP BY clause
✅ 更符合 SQL 标准
📌 Java 开发中:
-
MyBatis / JPA 生成的 SQL 更容易踩坑
-
需要显式聚合或分组
六、窗口函数增强
MySQL 8.0
SELECT
id,
amount,
SUM(amount) OVER (PARTITION BY user_id ORDER BY create_time) AS running_total
FROM orders;
✅ 支持
❌ 大数据量性能一般
MySQL 9.7.0
SELECT
id,
amount,
AVG(amount) OVER w AS avg_amt,
SUM(amount) OVER w AS sum_amt
FROM orders
WINDOW w AS (PARTITION BY user_id ORDER BY create_time);
✅ 支持 WINDOW 子句
✅ 执行效率更高
✅ SQL 更易维护
七、参数化 SQL 的行为差异
MySQL 8.0
PREPARE stmt FROM
'SELECT * FROM orders WHERE status = ?';
✅ 支持
❌ 类型推断较弱
MySQL 9.7.0
PREPARE stmt FROM
'SELECT * FROM orders WHERE status = CAST(? AS CHAR(20))';
✅ 类型检查更严格
✅ 更安全
✅ 减少隐式转换 bug
八、Java 场景下的实际影响总结
| 场景 | 8.0 | 9.7 |
|---|---|---|
| JSON CRUD | ❌ 难 | ✅ 极简 |
| 复杂报表 SQL | 慢 | ✅ Hypergraph |
| 递归结构 | 不稳定 | ✅ 稳定 |
| SQL 规范 | 宽松 | ✅ 严格 |
| 学习成本 | 低 | 稍高 |
九、最终结论(SQL 角度)
MySQL 9.7.0 不是"小版本升级",而是 SQL 能力的质变
✅ 如果你:
-
重度使用 JSON
-
写复杂报表
-
使用 CTE / 窗口函数
-
希望减少 Java 层逻辑
👉 9.7 的 SQL 优势极其明显