用户评论和用户属性
MySQL 8.0.21引入了在创建或更新用户账户时设置用户评论和用户属性的功能。用户评论由作为COMMENT子句参数传递的任意文本组成,通过CREATE USER或ALTER USER语句使用。用户属性由以JSON对象形式传递的数据组成,作为ATTRIBUTE子句参数传递给这两个语句之一。属性可以包含JSON对象表示法中的任何有效的键值对。在单个CREATE USER或ALTER USER语句中只能使用COMMENT或ATTRIBUTE中的一个。
用户评论和用户属性在内部作为一个JSON对象存储在一起,其中评论文本作为键为"comment"的元素的值。这些信息可以从Information Schema USER_ATTRIBUTES表的ATTRIBUTE列中检索;由于它以JSON格式存储,您可以使用MySQL的JSON函数和运算符来解析其内容。对用户属性的连续更改将与当前值合并,就像使用JSON_MERGE_PATCH()函数一样。
例如:
sql
mysql> CREATE USER 'mary'@'localhost' COMMENT 'This is Mary Smith\'s account';
Query OK, 0 rows affected (0.33 sec)
mysql> ALTER USER 'mary'@'localhost'
-≫ ATTRIBUTE '{"fname":"Mary", "lname":"Smith"}';
Query OK, 0 rows affected (0.14 sec)
mysql> ALTER USER 'mary'@'localhost'
-≫ ATTRIBUTE '{"email":"mary.smith@example.com"}';
Query OK, 0 rows affected (0.12 sec)
mysql> SELECT
-> USER,
-> HOST,
-> ATTRIBUTE->>"$.fname" AS 'First Name',
-> ATTRIBUTE->>"$.lname" AS 'Last Name',
-> ATTRIBUTE->>"$.email" AS 'Email',
-> ATTRIBUTE->>"$.comment" AS 'Comment'
-> FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER='mary' AND HOST='localhost'\G
*************************** 1. row ***************************
USER: mary
HOST: localhost
First Name: Mary
Last Name: Smith
Email: mary.smith@example.com
Comment: This is Mary Smith's account
1 row in set (0.00 sec)
新的optimizer_switch标志
MySQL 8.0.21在optimizer_switch系统变量中添加了两个新的标志,如下所述:
• prefer_ordering_index标志
默认情况下,当优化器确定使用有序索引可以更快执行带有LIMIT子句的ORDER BY或GROUP BY查询时,MySQL会尝试使用有序索引。然而,在某些情况下,选择不同的优化方式可能会实际表现更好。现在可以通过将prefer_ordering_index标志设置为off来禁用此优化。
该标志的默认值为on。
• subquery_to_derived标志
当将该标志设置为on时,优化器会将符合条件的标量子查询转换为对派生表的连接。例如,查询SELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)将被重写为SELECT t1.a FROM t1 JOIN ( SELECT COUNT(t2.a) AS c FROM t2 ) AS d WHERE t1.a > d.c。
此优化适用于SELECT、WHERE、JOIN或HAVING子句中的子查询,其中包含一个或多个聚合函数但没有GROUP BY子句,且不是相关的,并且不使用任何非确定性函数。
该优化也适用于作为IN、NOT IN、EXISTS或NOT EXISTS参数的表子查询,且不包含GROUP BY子句。例如,查询SELECT * FROM t1 WHERE t1.b < 0 OR t1.a IN (SELECT t2.a + 1 FROM t2)将被重写为SELECT a, b FROM t1 LEFT JOIN (SELECT DISTINCT 1 AS e1, t2.a AS e2 FROM t2) d ON t1.a + 1 = d.e2 WHERE t1.b < 0 OR d.e1 IS NOT NULL。
从MySQL 8.0.24开始,该优化还可以应用于相关标量子查询,通过对其应用额外的分组,然后在提升的谓词上进行外连接。例如,查询SELECT * FROM t1 WHERE (SELECT a FROM t2 WHERE t2.a=t1.a) > 0可以重写为SELECT t1.* FROM t1 LEFT OUTER JOIN (SELECT a, COUNT(*) AS ct FROM t2 GROUP BY a) AS derived ON t1.a = derived.a WHERE derived.a > 0。MySQL执行基数检查以确保子查询不返回多行(ER_SUBQUERY_NO_1_ROW)。
通常情况下,该优化被禁用,因为在大多数情况下它并不会带来明显的性能优势。该标志默认为off。
XML增强功能
从MySQL 8.0.21开始,LOAD XML语句现在支持导入XML中的CDATA节。
现在支持将数据转换为YEAR类型
从MySQL 8.0.22开始,服务器允许将数据转换为YEAR类型。CAST()和CONVERT()函数都支持单个数字、两位数字和四位数字的YEAR值。对于一位数字和两位数字的值,允许的范围是0-99。四位数字的值必须在1901-2155的范围内。YEAR还可以作为JSON_VALUE()函数的返回类型使用;该函数只支持四位数的年份。
字符串、日期时间和浮点数值都可以转换为YEAR类型。不支持将GEOMETRY值转换为YEAR类型。
将TIMESTAMP值作为UTC检索
从MySQL 8.0.22开始,支持将系统时区的TIMESTAMP列值在检索时转换为UTC DATETIME。使用CAST(value AT TIME ZONE specifier AS DATETIME)语法,其中specifier是[INTERVAL] '+00:00'或'UTC'之一。如果需要,可以通过指定精度高达6位小数的DATETIME值返回的参数来确定精度。在这种构造中,不支持ARRAY关键字。 还支持使用时区偏移插入到表中的TIMESTAMP值。不支持在CONVERT()或任何其他MySQL函数或构造中使用AT TIME ZONE。
Dump文件输出同步化
从MySQL 8.0.22开始,通过SELECT INTO DUMPFILE和SELECT INTO OUTFILE语句在写入文件时支持定期同步化。可以通过将select_into_disk_sync系统变量设置为ON来启用此功能;写入缓冲区的大小由select_into_buffer_size设置的值确定,默认为131072(217)字节。
此外,可以使用select_into_disk_sync_delay来设置同步到磁盘后的可选延迟时间,默认为无延迟(0毫秒)。
单次准备语句
从MySQL 8.0.22开始,准备语句只需准备一次,而不是在每次执行时都要准备。这是在执行PREPARE时完成的。对于存储过程内部的任何语句也是如此;当首次执行存储过程时,语句将被准备一次。
这个改变的一个结果是,准备语句中使用的动态参数的解析方式也按照以下方式进行了更改:
- 准备语句的参数在准备语句时被分配一个数据类型;该类型会保留在每次后续执行该语句时(除非重新准备该语句,见下文)。
- 对于在准备语句后续执行中使用的给定参数或用户变量,如果使用了不同的数据类型,可能会导致语句被重新准备;因此,建议在重新执行准备语句时使用相同的数据类型。
- 不再接受使用窗口函数的以下结构,以与SQL标准保持一致:
- NTILE(NULL)
- NTH_VALUE(expr, NULL)
- LEAD(expr, nn) 和 LAG(expr, nn),其中nn是负数 这有助于更好地符合SQL标准。请参阅各个函数的描述以获取更多详细信息。
- 在准备语句中引用的用户变量现在在准备语句时具有确定的数据类型,该类型会保留在每次后续执行该语句时。
- 在存储过程中出现的语句中引用的用户变量现在在第一次执行该语句时确定其数据类型,并且该类型会保留在任何后续调用该存储过程时。
- 当执行形如SELECT expr1, expr2, ... FROM table ORDER BY ? 的准备语句时,为参数传递一个整数值N不再导致结果按照选择列表中的第N条表达式排序;结果不再排序,而与使用ORDER BY常量时的预期一致。
- 仅在作为准备语句或存储过程中出现的语句中进行一次准备可以提高性能,因为它消除了重复准备的额外成本。这样做还可以避免可能的多个准备结构回滚,这是MySQL中许多问题的根源。
RIGHT JOIN作为LEFT JOIN的处理方式
从MySQL 8.0.22开始,服务器在内部将所有RIGHT JOIN实例作为LEFT JOIN处理,消除了在解析时没有完全转换的特殊情况。
派生条件下推优化
MySQL 8.0.22(以及更高版本)实现了针对具有物化派生表的查询的派生条件下推优化。对于诸如SELECT * FROM (SELECT i, j FROM t1) AS dt WHERE i > constant的查询,现在可以在许多情况下将外部WHERE条件下推至派生表,从而得到SELECT * FROM (SELECT i, j FROM t1 WHERE i > constant) AS dt的结果。
在以前,如果派生表被物化但没有合并,MySQL会将整个表进行物化,然后使用WHERE条件对行进行筛选。通过使用派生条件下推优化将WHERE条件移到子查询中,通常可以减少需要处理的行数,从而减少执行查询所需的时间。
当派生表不使用任何聚合或窗口函数时,外部WHERE条件可以直接下推到物化的派生表。当派生表使用GROUP BY但不使用任何窗口函数时,外部WHERE条件可以作为HAVING条件下推到派生表中。当派生表使用窗口函数且外部WHERE条件引用了窗口函数的PARTITION子句中使用的列时,WHERE条件也可以下推到派生表中。
派生条件下推默认情况下是启用的,可以通过optimizer_switch系统变量中的derived_condition_pushdown标志进行确认。这个标志在MySQL 8.0.22中添加,它默认设置为开启。要禁用特定查询的优化,可以使用NO_DERIVED_CONDITION_PUSHDOWN优化器提示(也是在MySQL 8.0.22中添加的)。如果由于设置derived_condition_pushdown为off而禁用了优化,可以使用DERIVED_CONDITION_PUSHDOWN来为特定查询启用优化。
派生条件下推优化不能应用于包含LIMIT子句的派生表。在MySQL 8.0.29之前,当查询包含UNION时也无法使用该优化。从MySQL 8.0.29开始,条件在大多数情况下可以下推到联合查询的两个查询块中。
此外,一个使用子查询的条件无法进行下推,而一个包含在外连接中的派生表作为内部表时,其WHERE条件也无法进行下推。
MySQL授权表上的非锁定(Non-locking)读取
从MySQL 8.0.22开始,为了允许对MySQL授权表进行并发的DML和DDL操作,之前在MySQL授权表上获取行锁的读操作被执行为非锁定读取。
现在在MySQL授权表上执行的非锁定读取操作包括:
• 通过连接列表和子查询从授权表读取数据的SELECT语句和其他只读语句,包括使用任何事务隔离级别的SELECT ... FOR SHARE语句。
• 使用任何事务隔离级别从授权表中读取数据(通过连接列表或子查询),但不修改它们的DML操作。