我使用的是 MySQL 8.0.32,我对内部转换有一些疑问,我不明白。除此之外,有时这种转换会显示在 SHOW FULL PROCESSLIST 中,因为它的执行时间太长。
这是我的桌子。
CREATE TABLE `provinces` (
`ID` VARCHAR(2) NOT NULL COLLATE 'utf8mb4_swedish_ci',
`PROVINCIA` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_swedish_ci',
PRIMARY KEY (`ID`)
) COLLATE='utf8mb4_swedish_ci' ENGINE=InnoDB;
我有 53 行这样的
ID | 省 |
---|---|
01 | 阿拉瓦 |
02 | 阿尔巴塞特 |
MySQL 函数是:
CREATE FUNCTION `get_provincia`( `id_provincia` VARCHAR(2) )
RETURNS varchar(45)
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE desc_provincia VARCHAR(45) DEFAULT '-';
SELECT PROVINCIA INTO desc_provincia
FROM provinces
WHERE ID = id_provincia;
RETURN desc_provincia;
END
该功能的 SHOW STATUS 显示:
- 字符集客户端: utf8mb4
- 排序规则连接:utf8mb4_0900_ai_ci
- 数据库排序规则:latin1_swedish_ci
该函数作为查询中的字段被调用。
SELECT customer_id, customer_name, ..., get_provincia(SUBSTRING(zip_code,1,2))...
FROM ...
当我使用 SHOW FULL PROCESSLIST 检查执行情况时,函数内部的查询显示如下:
SELECT provincia INTO desc_provincia
FROM provincias
WHERE id = NAME_CONST('id_provincia',_latin1'15' COLLATE 'latin1_swedish_ci')
因此,我有以下问题:
- 为什么 MySQL 强制使用 NAME_CONST?
- 这会给性能带来影响吗?我不明白为什么非常简单的查询会在 SHOW FULL PROCESSLIST 命令的“时间”列中显示“2”值,因为它需要 2 秒。
提前致谢。
我在 MySQL 版本上测试了您的示例
8.0.39-0ubuntu0.22.04.1
。我创建了以下函数
一个简单的 Bash 脚本来捕获
SHOW FULL PROCESSLIST
输出运行查询
制作
由于数据库排序规则设置 latin1_swedish_ci,导致使用 utf8mb4_swedish_ci 的省份表与使用 latin1_swedish_ci 的查询参数之间的排序规则不匹配。
通常每种排序规则转换都会影响性能,我们在 JOINS 等等中看到这一点。
我有什么建议?
修改要使用的函数参数
utf8mb4_swedish_ci
,并尽可能始终使用相同的排序规则。运行与上述相同的 SELECT 查询后,
SHOW FULL PROCESSLIST
结果为