【MySQL性能优化】- MySQL调优与8.0新特性

MySQL调优与8.0新特性

😄生命不息,写作不止

🔥 继续踏上学习之路,学之分享笔记

👊 总有一天我也能像各位大佬一样

🏆 博客首页 @怒放吧德德 To记录领地 @一个有梦有戏的人

🌝分享学习心得,欢迎指正,大家一起学习成长!

转发请携带作者信息 @怒放吧德德(掘金) @一个有梦有戏的人(CSDN)

1. 前言

前面学习了索引、执行计划、MySQL 执行过程、事务与锁、MVCC 以及 bufferpool 机制和日志,接下来就继续学习 MySQL 的调优以及 8.0 的新特性。

2. 全局优化

对于 MySQL 的优化,率先要考虑的是 SQL 与索引作为优化手段,这也是成本最低效果最好的方式,其次再去考虑表结构,接着在考虑系统配置,最后才去考虑硬件。

2.1 *MySQL 配置文件参数

MySQL 的配置文件有两种:my.ini(Windows)或 my.cnf(Linux)。

假设服务器以下配置:

  • CPU:32 核
  • 内存:64G
  • DISK:2T SSD

接下来介绍一些以上面的服务器配置来进行 MySQL 的配置参数。

注:修改配置文件上的参数,需要重启 MySQL 才能生效。

2.2 服务端参数 [mysqlId]

2.2.1 最大连接数

max_connections=3000

控制服务器允许同时建立的最大客户端连接数,这是调优的重要数据之一。当我们通过应用程序、用户或者工具来连接 MySQL 时,如果连接数已经达到最大值,新的连接就会被拒绝,会报 Too many connections的错误。

每个连接的创建和销毁都会占用一定的内存和系统资源(如线程、文件描述符)。合理设置该参数可避免服务器因连接过多导致资源耗尽,比如内存、文件句柄,业务所谓的支持多少并发,实际上就是每秒的请求数,也就是 QPS。

:::info 注意资源消耗:

每个连接至少需要占 256KB 内存,最大会到 64M,如果一个连接的请求数据超过 64M,比如进行了排序操作,这个时候就会申请临时空间,可能会将原来的内存中的数据清除,再将数据放到磁盘上。

(设置最大连接数需要根据实际情况进行合理设置,设置过高可能导致内存不足,反而会降低性能甚至引发 OOM )

:::

如果 3000 个用户同时连接上 MySQL,最小内存需要 3000256KB=750M,最大需要 300064M=192G。如果 innodb_buffer_pool 配置了 40G(配置为实际内存的 60%-70%),加上给操作系统分配 4G,那么给连接使用的空间就剩下不足 20G,然而如果连接过多,就会出现磁盘 SWAP(交换空间),此时就会影响服务器性能。

连接数过高不一定能够带来很大的吞吐量,反而可能会消耗更多的系统资源。

如何微调?

我们可以通过以下两个命令来查询当前活跃和历史最大的连接数。

java 复制代码
SHOW STATUS LIKE 'Threads_connected';  -- 当前活跃连接数
SHOW STATUS LIKE 'Max_used_connections'; -- 历史最高连接数

通过以下命令查看当前设置的最大连接数。

java 复制代码
SHOW VARIABLES LIKE 'max_connections';

当线上发生连接数过多,可以通过临时解决,以下命令是临时生效,重启后就会失效。

java 复制代码
SET GLOBAL max_connections = 1000;
2.2.2 允许用户最大连接数
java 复制代码
max_user_connections=2980

设置允许用户最大连接数为 2980,与设置最大连接数 3000 相差了 20,这 20 个连接数是为了防止 MySQL 被程序全部占用,导致 DBA 无法连接。

其默认值是 0 ,表示无限制

2.2.3 暂存连接数
java 复制代码
black_log=300

back_log 参数是 MySQL 缓存的尚未处理的连接数量,当 MySQL 在短时间内收到非常多的请求时,一时间处于不过来时,这个参数就会起到非常重要的作用。如果 MySQL 的连接数达到了最大连接数,那么多余的连接就会被暂存到堆栈中,等待某个连接释放资源。这个暂存数就是 black_log 配置的数据,如果超过了这个数量,超出的连接将会被拒绝。

假如最大连接数是 3000,暂存连接数是 300,那么,最多可以有 3300 个连接进来,300 个连接在堆栈中缓存。如果有 3301 个连接,那么多余的 1 个将会被拒绝。

2.2.4 非交互式空闲超时时间
java 复制代码
wait_timeout=300

指的是 app 应用程序通过 jdbc 连接 MySQL 进行操作完毕后,空闲 300 秒后会自动断开,默认是 28800 秒,也就是 8 小时。

关于等待超时最好是设置一下,默认 8 小时会很长,会导致连接数占用。当客户端在超时后尝试使用已关闭的连接会收到错误:Lost connection to MySQL server during query

2.2.5 交互式空闲超时时间
java 复制代码
interactive_timeout=300

指的是**通过命令行、图形化工具(Navicat)**等交互方式连接到 MySQL,并在指定时间内无操作时,服务器会自动关闭连接以释放资源。它与 wait_timeout 共同管理连接生命周期,但针对不同类型的客户端。默认也是 28800 秒=8 小时,这里建议与 wait_timeout 设置的时间一致。

对比:interactive_timeout vs wait_timeout

参数 作用对象 典型场景 默认值
interactive_timeout 交互式客户端 命令行、GUI 工具 28800 秒(8 小时)
wait_timeout 非交互式客户端 Web 应用、API 服务 28800 秒(8 小时)
2.2.6 Innodb 的几个参数
java 复制代码
innodb_thread_concurrency=64

这个是 MySQL InnoDB 存储引擎的一个配置参数,它用于控制 InnoDB 处理用户查询时的并发线程数量。默认值:0,表示不被限制,若要设置则与服务器的 CPU 核心数相同,或者是 CPU 核心数的 2 倍,如果超过配置的并发数,则需要排队,这个值的配置不建议太大,否则可能当并发量过大,操作同一条数据,这样会导致锁等待锁争用,甚至会导致死锁,会影响性能。

tip(不仅考虑服务器,还应考虑系统的并发数)

  • 对于小型服务器(<8 核):保持默认值 0,或设置为 2-4,避免线程争抢资源。
  • 对于中型服务器(8-32 核):可以尝试 8-32。
  • 对于大型服务器(>32 核):通常保持 0,让 InnoDB 自适应调度,或者进行压力测试找到最优值。
java 复制代码
innodb_buffer_pool_size=40G

innodb 存储引擎 buffer pool 缓存大小,一般设置物理内存的 60-70%(独立的 MySQL 服务器,没有其他主要进程),这个是越大越好,是来缓存数据页、索引页、插入缓冲、适配哈希索引等,目的是减少磁盘 I/O,从而提升数据库性能。

java 复制代码
innodb_lock_wait_timeout=10

MySQL InnoDB 存储引擎中的一个参数,用于控制 事务等待行锁 的最大时间(以秒为单位)。如果某个事务等待锁的时间超过该值,MySQL 会终止该事务并报错。

行锁锁定时间,默认 50 秒,这个需要根据实际业务情景来设定。

java 复制代码
innodb_flush_log_at_trx_commit=1

决定事务提交时日志(redo log)刷盘的策略 ,直接影响数据一致性、性能和崩溃恢复

该参数有 0、1、2 三种取值,每个值的行为不同:

刷新策略 性能 数据安全性
0 事务提交时 ,日志写入 日志缓冲区 (不立刻刷盘),每秒一次将日志写入磁盘 (减少 I/O 操作) 可能丢失 1 秒内事务数据
1(默认) 事务提交时立刻将日志写入磁盘(fsync) (每次提交都涉及磁盘 I/O) 最高(事务提交后保证持久化)
2 事务提交时 ,日志写入 日志缓冲区 ,但不立即 fsync,每秒一次 刷盘 可能丢失 1 秒内事务数据

场景:

  • 强一致性场景(电商、支付、订单等),像这些场景推荐配置 1,需要保证事务提交后数据不会丢失,即使 MySQL 奔溃。
  • 高并发或性能优先(电商、社交、日志系统等),推荐配置 2,减少对磁盘写入压力,可能丢失 1 秒的数据。
java 复制代码
sync_binlog=1

MySQL 二进制日志(binlog)同步 相关的关键参数,决定了 binlog 写入到磁盘的频率,直接影响数据安全性、事务持久性和性能

当事务提交时,MySQL 会将 二进制日志(binlog) 写入操作系统缓存,但不会立即刷入磁盘sync_binlog 控制每多少次事务提交后,执行一次 fsync() ,确保 binlog 持久化到磁盘。

sync_binlog 可取值 0 或正整数

刷盘时机 性能 数据安全性
0 让操作系统 自行决定 何时刷盘 最高(减少磁盘 I/O) 最差(崩溃可能丢失大量事务)
1(最安全) 每次事务提交后立即 fsync,确保 binlog 立即写入磁盘 最低(每次提交都涉及 I/O) 最安全(不会丢失已提交事务)
N(如 100, 1000) 每 N 个事务提交后 fsync 一次 性能较高(减少 I/O) 可能丢失最近 N 个事务
2.2.7 排序缓存大小
java 复制代码
sort_buffer_size=4M

每个需要排序的线程分配该大小的一个缓冲区,增加该值可以加速 ORDER BY 或 GROUP BY 的操作。

sort_buffer_size 是 connection 级别,即在每个 connection(session) 第一次需要使用这个 buffer 时候,一次性分配设置的内存。

这个参数的设置并不是越大越好,它是 connection 级别,需要考虑到连接数占用资源大小,比如有 500 个连接需要进行排序,会分配内存资源,也就是 500*sort_buffer_size(4M)=2G。(要根据业务情况、服务器配置、并发数来进行修改)

2.2.8 表关联缓存大小
java 复制代码
join_buffer_size=4M

用于表关联缓存的大小,和sort_buffer_size 一样,该参数对应的分配内存也是每个连接独享。

3. MySQL8.0 新特性

3.1 降序索引

MySQL 8.0 引入了对 降序索引(Descending Indexes) 的原生支持,这一特性显著优化了特定查询场景下的性能,尤其是涉及降序排序或混合排序方向的查询。

他是对排序进行了优化,避免还需要用到文件排序(using filesort),即通过执行计划的期望是Extra 列应显示 Using index,而非 Using filesort。

以下 8.0 的例子,创建一张表,并且创建了降序索引。

java 复制代码
create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
-- 插入几条数据
insert into t1 (c1,c2) values(1, 10),(2,50),(3,50),(4,100),(5,80);

通过 Explain 来看一下情况

java 复制代码
explain select * from t1 order by c1,c2 desc; 

可见 Extra 列的数据是 Using index 使用了索引,并不是文件排序,如果是 5.7 版本的 MySQL,虽然会有 Using index,会使用索引,但是也会 Using filesort 。

如果将 c1,c2 的排序换了个位置

java 复制代码
explain select * from t1 order by c1 desc, c2; 

通过执行计划可以看到,也是用到了降序索引,但是还会多了一个 Backward index scan;反向扫描。

那如果没有使用倒序,通过 c1、c2 正序排序。

java 复制代码
explain select * from t1 order by c1, c2; 

很显然需要用到文件排序,这是因为没有正序的索引树,排序必须按照每个字段定义的排序或按相反顺序才能充分利用索引。

当然,如果是 c1、c2 顺序不同进行排序,也会出现文件排序。

java 复制代码
explain select * from t1 order by c2 desc, c1; 

这是因为MySQL 只能利用索引的最左前缀顺序来优化排序。如果 ORDER BY 的列顺序与索引不匹配(即使包含全部索引列),优化器无法直接使用索引的有序性,必须进行额外排序。

3.2 group by 不再隐式排序

MySQL8.0 对于 group by不再会自动隐式排序,如果需要排序,那就必须要加上 order by 语句。在 MySQL5.7 版本,是用了 group by 的时候,MySQL 会自动进行排序。

在 8.0 版本中,使用 t1 这张表来分析,执行 SQL,通过 c2 这列进行 group by。

可以看到 8.0 版本并不会自动排序,c2 列是没有排序。如果是 5.7 版本来执行这句 SQL 将会进行排序(这里就不再运行演示)。

3.3 隐藏索引

使用 Invisible 关键字将索引设置为隐藏索引,允许开发者将索引标记为"不可见",使查询优化器忽略该索引,而无需实际删除索引。这一特性在索引维护、性能测试和灰度验证场景中非常实用。

隐藏索引只是不可见,但是数据库后台还是会维护隐藏索引,在查询时优化器是不会使用该索引,哪怕是使用 force index 也是不会使用,并且也不会报错,这个索引是实际存在的,需要的时候也可以恢复。注:主键不能设置 invisible

如下例子

java 复制代码
create table t2(c1 int, c2 int, index idx_c1(c1), index idx_c2(c2) invisible);

创建一张表 t2,并且创建了 c1 和 c2 两个索引,c2 索引设置了隐藏索引。

先来查看一下 t2 表的索引结构

java 复制代码
show index from t2\G

主要看 Visible字段,idx_c1 是可见的,idx_c2 是不可见的。

我们先通过 c1 进行查询,通过执行计划可以看到能够走索引。

java 复制代码
explain select * from t2 where c1=1

接下来我们通过 c2 进行查询

java 复制代码
explain select * from t2 where c2=1;

可见 c2 查询没有走索引,而是进行了全表扫描。idx_c2 是隐藏索引,虽然不会去使用,但是实际还是存在的。

那么如果还想使用这个隐藏索引,可以将索引设置为可见或者设置隐藏索引可用。

① 通过设置参数

我们可以通过以下命令查看参数。

java 复制代码
select @@optimizer_switch\G

其中的 use_invisible_indexes=off(默认是 off),能够查看 MySQL 是不是开启了使用隐藏索引。(设置参数可以有 GLOBAL(全局设置,重启失效)SESSION(当前会话有效)my.ini / my.cnf (配置文件设置,需要重启才生效) )。

我们先通过当前会话有效的来设置。

java 复制代码
set session optimizer_switch="use_invisible_indexes=on";

设置成功我们再来看一下通过 c2 进行查询。

这时候,查询优化器就能够使用到隐藏索引了。

② 通过设置索引可见性

可以通过 visible 或者 invisible 来设置可见性。

java 复制代码
alter table t2 alter index idx_c2 visible;
alter table t2 alter index idx_c2 invisible;

3.4 函数索引

MySQL 8.0 引入了 函数索引(Functional Indexes),允许在索引中使用表达式或函数处理后的列值,从而优化基于函数或表达式的查询性能。

函数索引基于虚拟列功能实现,在 MySQL 中相当于新增了一个列,这个列会根据函数来进行计算结果值,然后函数索引的时候就会用这个计算后的列作为索引。

接下来再创建一个表 t3,并且创建两个索引,一个普通索引,一个函数索引。

java 复制代码
create table t3(c1 varchar(10),c2 varchar(10));
-- 普通索引
create index idx_c1 on t3(c1);
-- 大写函数索引
create index func_idx on t3((UPPER(c2)));

查看一下表结构 show index from t3\G

对比两个索引,函数索引会在表达式中显示。

通过执行计划查看,当我们对 c1 字段进行使用转换大写的函数,可以看到是不会使用索引,即便是普通索引也不会使用到。

java 复制代码
explain select * from t3 where upper(c1)='Liyd';

当对 c2 使用函数,就能够使用到函数索引。

java 复制代码
explain select * from t3 where upper(c2)='Liyd';

实际上函数索引的原理就是将函数(upper(c2))的结果放到了索引树中。注:不建议频繁使用函数索引。

3.5 innodb 存储引擎跳过锁等待

对于 select ... for share(8.0 新增查询共享锁)或 select ... for update,在语句后面添加 NOWAITSKIP LOCKED语法可以跳过锁等待,或者跳过锁定。

在 5.7 版本之前,使用 select ... for update,如果获取不到锁,会一直等待,直到 innodb_lock_wait_timeout 超时。

在 8.0 版本,可以通过添加 nowait、skip locked 语法,能够立即返回。如果查询的行已经加锁,那么 nowait 会立即报错返回,而 skip locked 也会立即返回,只是返回结果不包含被锁定的行。

通过 t1 表来做示例。

首先在 session1 中开启事务,对 c1=2 的数据进行更新,接着在 session2 中使用 for update 进行查询,这时候 c1=2 已经被行锁了,获取不到锁会一直卡住,直到锁超时。

但加上 nowait 之后,会立即报错返回。

当使用 skip locked 进行查询表数据的时候,c1=2 的这条数据将会被跳过。

3.6 自适应参数

innodb_dedicated_server参数会让 innodb 自动去根据检测到的内存大小自动配 innodb_buffer_pool_size,innodb_log_file_size等参数,会尽可能多的占用系统资源来提高性能。

这个值默认是关闭的(off),不建议开启。可以通过以下命令查看。

java 复制代码
show variables like '%innodb_dedicated_server%';

3.7 死锁检查控制

innodb_deadlock_detect用来控制服务器是否执行 innodb 死锁检查,默认是打开的。死锁检查会占用系统资源,对于高并发系统,可以关闭死锁检查,但是还确保系统极少情况发送死锁,同时把等待超时时间设置小点,防止死锁时间过长。

java 复制代码
show variables like '%innodb_deadlock_detect%'

3.8 undo文件不再使用系统表空间

MySQL 8.0 默认不再将 Undo 日志存储在系统表空间(ibdata1)中,而是引入了独立的 Undo 表空间机制。这一设计优化了 Undo 日志的管理效率,并提升了事务并发性能。

从 MySQL 8.0 开始,默认会创建两个独立的 Undo 表空间(innodb_undo_001.ibu 和 innodb_undo_002.ibu),专门用于存储 Undo 日志。系统表空间(ibdata1)不再包含 Undo 数据。

用户可以通过参数 innodb_undo_tablespaces 配置 Undo 表空间的数量(默认值为 2),并支持在运行期间动态添加或删除 Undo 表空间。

3.9 binlog 过期时间精确到秒

在 8.0 之前,单位是,并且binlog日志过期时间设置都是设置expire_logs_days参数,而在 8.0 版本之后,MySQL默认使用binlog_expire_logs_seconds参数。

3.10 字符集变动

在8.0版本之前,默认字符集为latin1,utf8指向的是utf8mb3,8.0版本默认字符集为utf8mb4,utf8默认指向的也是utf8mb4。

3.11 MyISAM系统表全部换成InnoDB表

8.0 版本之后,将系统表(mysql)和数据字典表全部改为InnoDB存储引擎,默认的MySQL实例将不包含MyISAM表,除非手动创建MyISAM表。

3.12 元数据存储变动

MySQL 8.0 删除了之前版本的元数据文件,例如表结构 .frm 等文件,全部集中放入 **mysql.ibd **文件里。

3.13 自增变量持久化

在8.0之前的版本,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置 AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。在 8.0 之后,对 AUTO_INCREMENT 进行了持久化。

当数据 id 为自增的时候,假如插入了三条数据,正常来说自增 id 会从 1 开始到 3,此时如果把 id=3 的数据删除了,在 5.7 版本数据库的时候,重启服务,再次插入数据,id 依然是 3 开始,假如说此时把 id=3 改成 id=5,在连续插入两条数据的时候,就会报错( ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY')。

如果是 8.0 版本,把 id=3 的数据删除,重启服务之后再次插入数据,id 会持续自增为 id=4。

3.14 DDL 原子化

从 8.0 开始,innodb 表的 DDL 支持事务完整性,其中与表相关的原子 DDL 只支持 InnoDB 存储引擎。

一个原子 DDL 操作内容包括:更新数据字典,存储引擎层的操作,在 binlog 中记录 DDL 操作。支持与表相关的 DDL:数据库、表空间、表、索引的 CREATE、ALTER、DROP 以及 TRUNCATE TABLE。支持的其它 DDL :存储程序、触发器、视图、UDF 的 CREATE、DROP 以及ALTER 语句。支持账户管理相关的 DDL:用户和角色的 CREATE、ALTER、DROP 以及适用的 RENAME等等。

在 5.7 之前,如果通过

java 复制代码
drop table t1,t2;

删除两张表的时候,如果 t2 不存在,t1 存在,此时会报错(t2 不存在),但是 t1 已经是被删除了。

在 8.0 之后,如果删除报错了,就会回滚,两张表都会还在。

3.15 参数修改持久化

MySQL 8.0版本支持在线修改全局参数并持久化,通过加上PERSIST关键字,可以将修改的参数持久化到新的配置文件(mysqld-auto.cnf)中,重启MySQL时,可以从该配置文件获取到最新的配置参数。set global 设置的变量参数在mysql重启后会失效。

系统会在数据目录下生成一个包含json格式的mysqld‐auto.cnf 的文件,格式化后如下所示,当my.cnf 和mysqld‐auto.cnf 同时存在时,后者具有更高优先级。

3.16 窗口函数

窗口函数(Window Functions) 的支持,这一功能极大增强了 SQL 的分析能力,允许用户在不合并行的前提下对数据集进行复杂的分组、排序和聚合操作。

窗口函数与 SUM()、COUNT() 这种分 组聚合函数类似,在聚合函数后面加上over()就变成窗口函数了,在括号里可以加上partition by等分组关键字指定如何分组,窗 口函数即便分组也不会将多行查询结果合并为一行,而是将结果放回多行当中,即窗口函数不需要再使用 GROUP BY。

通过以下例子来学习

java 复制代码
-- 首先要创建一个新的表
CREATE TABLE `account_channel` (
	`id` INT NOT NULL AUTO_INCREMENT,
	`name` VARCHAR ( 255 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '姓名',
	`channel` VARCHAR ( 20 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '账户渠道',
	`balance` INT DEFAULT NULL COMMENT '余额',
PRIMARY KEY ( `id` ) 
) ENGINE = INNODB
-- 插入几条数据
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '1', 'Liyd', 'wx', '100' );
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '2', 'Liyd', 'alipay', '200' );
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '3', 'Liyd', 'yinhang', '300' );
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '4', 'Lixd', 'wx', '200' );
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '5', 'Lixd', 'alipay', '100' );
INSERT INTO `account_channel` ( `id`, `name`, `channel`, `balance` )
VALUES
	( '6', 'Lidd', 'wx', '500' );

假如需要通过用户分组查看各个用户的所有账户合起来有多少钱。一般来说我们会通过 sum 求和配合 group by 来实现查询。

java 复制代码
select name,sum(balance) from account_channel group by name;

在聚合函数后面加上 over()变成分析函数,后面也不用添加 group by 分组,在over里已经用partition关键字指明了如何分组计算,这种可以保留原有表数据的结构,不会像分组聚合函数那样每组只返回一条数据。

java 复制代码
SELECT
	*,
	sum( balance ) over ( PARTITION BY NAME ) AS sum_balance 
FROM
	account_channel;

还能加上 order by 进行排序

java 复制代码
SELECT
	`name`,
	channel,
	balance,
	sum( balance ) over ( PARTITION BY NAME ORDER BY balance DESC ) AS sum_balance 
FROM
	account_channel;

但是对应的求和是分组的当前与上一个之和,例如对于 Liyd的数据来说,第一条是 yinhang,对应 300,求和就是 300,第二条是 alipay,对应是 200,求和是 300+200=500,是逐步求和所得的结果。

如以下不带 DESC 的结果

如果over()里如果不加条件,则默认使用整个表的数据做运算,求和计算将会全表求和。

还可以进行平均值

java 复制代码
SELECT NAME
	,
	channel,
	balance,
	avg( balance ) over ( PARTITION BY NAME ) AS avg_balance 
FROM
	account_channel;

专用窗口函数:

  • 序号函数:ROW_NUMBER()、RANK()、DENSE_RANK()
  • 分布函数:PERCENT_RANK()、CUME_DIST()
  • 前后函数:LAG()、LEAD()
  • 头尾函数:FIRST_VALUE()、LAST_VALUE()
  • 其它函数:NTH_VALUE()、NTILE()

例如通过 balance 排序,输出序号。

java 复制代码
SELECT `name`
	,
	channel,
	balance,
	row_number() over ( ORDER BY balance ) AS num 
FROM
	account_channel;

窗口函数能简化复杂查询逻辑,提升代码可读性和执行效率。合理使用窗口函数可避免冗余的子查询和临时表操作,尤其适用于报表生成、趋势分析和实时计算场景。

4. 总结

本文主要介绍了 MySQL 的调优方法和 8.0 版本的新特性。在调优方面,强调了 SQL 与索引优化的重要性,以及表结构、系统配置和硬件的优化顺序。详细讲解了多种配置参数的设置和调整方法,包括最大连接数、暂存连接数、空闲超时时间、Innodb 相关参数、排序缓存大小和表关联缓存大小等,这些参数的合理设置对于提高 MySQL 性能和稳定性至关重要。

在 MySQL 8.0 新特性方面,列举了降序索引、group by 不再隐式排序、隐藏索引、函数索引、innodb 存储引擎跳过锁等待、自适应参数、死锁检查控制、undo文件不再使用系统表空间、binlog 过期时间精确到秒、字符集变动、MyISAM系统表全部换成InnoDB表、元数据存储变动、自增变量持久化、DDL 原子化、参数修改持久化和窗口函数等一系列新特性。这些新特性从不同方面提升了 MySQL 的功能和性能,如优化查询效率、增加索引管理的灵活性、提高事务处理的效率等。通过合理运用这些新特性,可以更好地满足现代应用程序对数据库的高性能和高可用性需求。


转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

持续创作很不容易,作者将以尽可能的详细把所学知识分享各位开发者,一起进步一起学习。转载请携带链接,转载到微信公众号请勿选择原创,谢谢!

👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍

谢谢支持!

相关推荐
samroom7 分钟前
Vue+Node.js+MySQL+Element-Plus实现一个账号注册与登录功能
vue.js·mysql·node.js
小蒜学长43 分钟前
乡政府管理系统设计与实现(代码+数据库+LW)
数据库·spring boot·后端·学习·旅游
why1511 小时前
go个人论坛项目
开发语言·后端·golang
秋凉 づᐇ1 小时前
每日一题------面试
面试·职场和发展
暮色妖娆丶1 小时前
利用 Caffeine 缓存不适合存储在配置中心的配置项
java·后端·架构
钢板兽1 小时前
力扣hot100二刷——链表
后端·算法·leetcode·链表·面试
只做开心事2 小时前
MySQL基本查询
数据库·mysql
池鱼ipou2 小时前
春招面试拷打实录(一):揭秘高频难题与应对策略🧐
前端·vue.js·面试
树上有只程序猿2 小时前
MySQL时间溢出原理、影响与解决方案
mysql
Amber_372 小时前
Cursor配置Golang开发环境
开发语言·后端·golang