MySQL 8.0的新特性

阅读 249
标签: MySQL

MySQL 5.7 已经停止更新。官方的 EOL(End of Life,生命周期终止)日期是 2023 年 10 月 21 日,这意味着 Oracle 已不再提供任何安全补丁、错误修复或官方支持。MySQL 8.0 相比 5.7 版本带来了一些新特性和优化。

首先,我们来看看几个新特性: 

Common Table Expression

公用表表达式:Common Table ExpressionCTE。它可以让 SQL 语句的结构更加清晰,特别是在需要多次使用相同逻辑的查询时,可以避免嵌套子查询导致的可读性差的问题。

sql
WITH recent_orders AS (
SELECT customer_id, total_amount
FROM orders
WHERE order_date > NOW() - INTERVAL 7 DAY
)

上面代码中,使用了 WITH 关键字来定义一个 CTE,它的作用类似于一个临时的查询结果集,可以在后续的 SELECT 语句中使用。这样,后续就可以使用:

sql
SELECT * FROM recent_orders;

来查询这个结果集中的内容。

相比子查询方式,如果查询逻辑较复杂,可以优先考虑 CTE,因为CTE可以让 SQL 更易读、易容易维护。

窗口函数

相比传统的 GROUP BY 方式,窗口函数使 MySQL 8.0 能够执行更强大的数据分析,提高了查询的灵活性和性能。来看一个例子:

在 employees 表中已经有如上数据,现在需要按照部门对每个员工按照薪资进行降序排序,可以使用窗口函数:

sql
SELECT
id,
name,
department,
salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS `rank` FROM employees;

得到结果如下:

如果不使用窗口函数,需要用变量的方式:

sql
SET @rank = 0;
SET @dept = '';
SELECT id, name, department, salary, `rank`
FROM (
SELECT
id, name, department, salary,
@rank := IF(@dept = department, @rank + 1, 1) AS `rank`,
@dept := department
FROM employees
ORDER BY department, salary DESC
) t;

导致查询更复杂、更低效,特别是涉及到跨行计算时。窗口函数在 MySQL 8.0 中更简洁高效,能大幅简化 SQL 语句。

降序索引

在 MySQL 5.7 及之前,索引默认是升序(ASC),即使你在 ORDER BY column DESC 进行查询,索引仍然是升序存储,查询时需要额外的排序操作。

在 MySQL 8.0 及以上版本中,降序索引(Descending Index) 允许索引按照降序(DESC) 排序,以提高查询效率。

来看一个简单例子:

sql
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
age INT
);
-- 创建降序索引
CREATE INDEX idx_age_desc ON users (age DESC);

我们创建了一个表users,并且给 age 字段加了一个降序索引。插入一点数据:

sql
INSERT INTO users (id, name, age) VALUES
(1, 'Alice', 25),
(2, 'Bob', 30),
(3, 'Charlie', 20);

然后,使用降序索引的查询:

sql
EXPLAIN SELECT age FROM users ORDER BY age DESC;

结果如下:

可以看到,在查询时,默认使用了这个降序索引。

隐藏索引

MySQL 8.0 引入了 隐藏索引(Invisible Index)的概念。一个隐藏索引在数据库优化器中不可见,也就是说,查询优化器不会使用该索引,但索引数据仍然会被维护(插入、更新、删除数据时仍会更新索引)。

这个特性能够方便我们测试索引对查询性能的影响。

比如,我们可以先隐藏索引,观察查询性能是否受影响。如果没有影响,可以删除索引;如果有影响,可以恢复索引的可见性,而无需重新创建索引。

假设 users 表的 age 字段有一个索引:

sql
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
age INT,
email VARCHAR(100),
INDEX idx_age (age) -- 创建 age 列的索引
);

我们可以将其设置为隐藏索引:

sql
ALTER TABLE users ALTER INDEX idx_age INVISIBLE;

此时,索引 idx_age 对查询优化器不可见,查询不会使用该索引。

如果发现查询性能下降,可以恢复索引:

sql
ALTER TABLE users ALTER INDEX idx_age VISIBLE;

idx_age又会被查询优化器使用。

通过隐藏索引可以安全地管理索引,避免盲目删除重要索引导致的查询性能下降。

性能优化

除了提供一些新特性外,mysql 8.0还针对性能做了一些优化。在高并发、大数据处理、JSON处理上, MySQL 8.0做了大量优化,提升了整体性能。

但具体到底提升了多少呢?有网友在硬件参数相同的情况下进行了基准测试:

bash
vCPUS: 4
内存:16G

并且,为这个基准测试设置了几个值得注意的变量:

bash
innodb_max_dirty_pages_pct = 90 #脏页百分比,90为默认值
innodb_flush_neighbors=0 #关闭刷新邻接页功能开启
innodb_buffer_pool_instances=8 #新数据库缓冲池实例=8
innodb_buffer_pool_size=8GiB #新数据库缓冲池大小=8GiB

两个 MySQL具体版本为:

bash
MySQL 5.7版本:MySQL社区服务器 - GPL 5.7.24
MySQL 8.0版本:MySQL社区服务器 - GPL 8.0.14

MySQL 5.7 和 MySQL 8.0 这两个节点都处于休眠状态,没有活动连接经过这些节点,因此它本质上是一个纯粹的基准测试。得到的读取速度对比图如下:

可以看到,在线程数量大于512后,mysql8.0的读取速度明显高于mysql5.7。这表明,8.0版本在高并发场景下会有更好的表现。

参考

最后编辑于: 2025-03-15

评论(0条)

(必填)
复制成功