文章目录
1. mysql8.0 的重要更新
建议使用8.0.17及之后的版本,更新的内容比较多,挑几个重要的使用上的更新,其他请参考官网
- 新增函数索引:之前我们知道,如果在查询中加入了函数计算,索引不生效,就是所谓的
索引列上无计算,但在MySQL 8.0.13开始支持在索引中使用函数(表达式)的值。创建函数索引:create index nameIdx on t3( (UPPER(name)) ); 创建一个name列的大写的函数索引原理:函数索引基于虚拟列功能实现,在MySQL中相当于新增了一个列,这个列会根据你的函数来进行计算结果,然后使用函数索引的时候就会用这个计算后的列作为索引
- 新增降序索引:MySQL在语法上很早就已经支持降序索引,但实际上创建的仍然是升序索引。mysql8.0开始真正支持降序索引
创建降序索引:create index nameAgeIdx on t3( name ,age desc); 创建一个name列升序,age降序的索引对比:mysql 5.7中通过explain查看也会使用索引,但是Extra字段里有filesort文件排序,但mysql8.0中的Extra字段里没有filesort文件排序,充分利用了降序索引
- innodb存储引擎 select for update 跳过锁等待:对于select … for share(8.0新增加查询共享锁的语法)或 select … for update, 在语句后面添加
NOWAIT、SKIP LOCKED语法可以跳过锁等待,或者跳过锁定在5.7及之前的版本: select…for update,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时在8.0版本: select…for update NOWAIT 通过添加NOWAIT、SKIP LOCKED语法,能够立即返回。如果查询的行已经加锁,那么NOWAIT会立即报错返回,而SKIP LOCKED也会立即返回,只是返回的结果中不包含被锁定的行。- 应用场景比如查询余票记录,如果某些记录已经被锁定,用
SKIP LOCKED可以跳过被锁定的记录,只返回没有锁定的记录,提高系统性能
- group by 不再隐式排序 : mysql 8.0 对于group by 字段不再隐式排序,如需要排序,必须显式加上order by 子句。
- .frm等元数据存储变动 : MySQL 8.0删除了之前版本的元数据文件,例如表结构
.frm等文件,全部集中放入mysql.ibd文件里。 - 窗口函数:从 MySQL 8.0 开始,新增了一个叫窗口函数的概念,它可以用来实现若干新的查询方式。窗口函数即便分组也不会将多行查询结果合并为一行,而是将结果放回多行当中。下文会对窗口函数做详细的使用介绍
参考文档
mysql8.0 添加弃用和删除的特性
mysql8.0 添加弃用和删除的参数
mysql8.0 InnoDB架构
2. 窗口函数的组成部分
窗口函数不会改变原有sql的查询结果,更像是在原有查询的基础上增加一个列,用于计算部分逻辑。作为执行计算的函数,窗口函数主要由三部分组成,如下:
2.1 窗口函数本身
-
①:排名函数
ROW_NUMBER():计算行号。为每一行分配一个唯一的整数,从1开始递增。RANK():计算排名,排名可能不连续。对每一行进行排名,当遇到相同值时,排名会跳过一些数字。DENSE_RANK():计算排名,排名是连续的。对每一行进行排名,但不会跳过排名数字,即使遇到相同值。
-
①:聚合函数
MAX(列名):计算窗口中的最大值。MIN(列名):计算窗口中的最小值。SUM(列名):对窗口中的数据求和。AVG(列名):对窗口中的数据求平均值。COUNT(列名):计算窗口中的记录数。STDDEV(列名):计算总体标准差。使用公式 S = sqrt(sum((x_i - x_bar)^2) / N),其中 N 是样本中的数据点数量。STDDEV_SAMP(列名):计算样本标准差。使用公式 S = sqrt(sum((x_i - x_bar)^2) / (N - 1)),其中 N 是样本中的数据点数量。
-
①:偏移函数
LAG(列名,行数):取当前行往前(朝分区头部方向)第N行数据的值。LEAD(列名,行数):取当前行往后(朝分区尾部方向)第N行数据的值。
-
①:首尾函数
FIRST_VALUE(列名):取窗口内第一行的值。LAST_VALUE(列名):取窗口内最后一行的值。NTH_VALUE(列名,N):取窗口内第N行的值。
-
①:分布函数
PERCENT_RANK():计算行的百分比排名。输出百分比格式。CUME_DIST():计算行相对于所有其他行的累积分布。NTILE(N):将数据顺序切分成N等份,返回数据所在等份的编号(从1到N)。
2.2 over子句
over子句定义了窗口函数的计算范围。它由三部分组成
PARTITION BY:将结果集分成多个独立的分区,每个分区都是一个独立的数据集,窗口函数在每个分区上独立计算。如果省略,整个数据集被视为一个单一的分区。ORDER BY:在每个分区内对行进行排序。- 对于排名函数,ORDER BY 子句决定了行的排名顺序。
- 对于聚合函数,ORDER BY 子句决定了窗口的计算顺序。
窗口框架:窗口框架用于定义在当前分区内,哪些行会被包含在窗口函数的计算中。它必须与ORDER BY子句一起使用(如果没有ORDER BY,则整个分区被视为一个框架),下面介绍一下窗口框架的特性-
语法:
{ROWS | RANGE | GROUPS} BETWEEN frame_start AND frame_end。其中frame_start和frame_end可以是以下之一UNBOUNDED PRECEDING:分区的第一行UNBOUNDED FOLLOWING:分区的最后一行CURRENT ROW:当前行n PRECEDING:当前行之前的n行(对于ROWS)或值(对于RANGE)n FOLLOWING:当前行之后的n行(对于ROWS)或值(对于RANGE)- 注意:n PRECEDING 和 n FOLLOWING中的n必须是非负整数常量
-
默认窗口框架
- 如果
指定了ORDER BY而没有指定窗口框架,则默认框架为:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,这意味着窗口函数会计算从分区开始到当前行(包括当前行)的所有行,但是注意,这里使用的是RANGE,所以它会包括所有与当前行在ORDER BY列上具有相同值的行(即并列的行) - 如果
没有指定ORDER BY,也没有指定窗口框架,则默认框架为:ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,这意味着整个分区都会被包含在窗口内。
- 如果
-
ROWS 、RANGE 和 GROUPS 的区别
假设有如下一张表table,则用该表来解释这三者的区别id value 1 10 2 20 3 20 4 30 -
ROWS:基于物理行(行号)移动或后退一行,用行数来指定偏移量,当order by字段出现相同的值时,不考虑并列,每行独立计算。使用 ROWS 的查询sql如下:SELECT id, value, SUM(value) OVER (ORDER BY value ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sum_rows FROM table;使用 ROWS ,每条数据与前后移动一行的值进行
sum,结果如下:id value sum_rows rows 计算过程1 10 3010(当前) + 20(后1行) = 302 20 5010(前1行) + 20(当前) + 20(后1行) = 503 20 7020(前1行) + 20(当前) + 30(后1行) = 704 30 5020(前1行) + 30(当前) = 50 -
RANGE:基于逻辑值(ORDER BY列的值)来增加或减少对应的值,用值来指定偏移量(需要与ORDER BY列类型兼容),当order by字段出现重复的值时,并列的行也加入计算范围,使用 RANGE 的查询sql如下:SELECT id, value, SUM(value) OVER (ORDER BY value RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING) AS sum_range FROM table;使用 RANGE ,每条数据与 前后 ±10的数据范围所涵盖的记录进行
sum,当出现并列的重复值时,列入计算范围,结果如下:id value sum_range range 计算过程1 10 50值范围 [0,20]所涵盖的行 → id1(10), id2(20), id3(20) → 10+20+20= 502 20 80值范围 [10,30]:id1(10), id2(20), id3(20), id4(30) → 10+20+20+30= 803 20 80值范围 [10,30]:id1(10), id2(20), id3(20), id4(30) → 10+20+20+30= 804 30 70值范围 [20,40]:id2(20), id3(20), id4(30) → 20+20+30= 70 -
GROUPS(MySQL 8.0.14+):GROUPS介于ROWS和RANGE之间,它按组(一组在ORDER BY列上值相同的行)进行偏移,并列的行会被视为同一组,使用 GROUPS的查询sql如下:SELECT value, SUM(value) OVER (ORDER BY value GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sum_groups FROM table; 结果: value | sum_groups 10 | 10+20 = 30 -- 当前组(10),前一组没有,后一组(20)所以包括10和20(整个组) 20
-
-

1618

被折叠的 条评论
为什么被折叠?



