尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MySQL 8.0 字符集与排序规则(Collation)对查询计划与回表性能的深水区影响

MySQL 8.0 字符集与排序规则(Collation)对查询计划与回表性能的深水区影响 MySQL 8.0 字符集与排序规则Collation对查询计划与回表性能的深水区影响在 MySQL 数据库性能排障的深水区案例中有一种极其隐蔽、杀伤力极大、且极难被普通开发人员察觉的慢查询陷阱——字符集Charset与排序规则Collation不一致引发的“隐式类型转换与索引完全失效”很多团队在建表时缺乏全库统一规范核心用户表t_user是在 MySQL 5.7 时代建的使用的是历史默认的utf8mb4_general_ci而新业务订单表t_trade_order是在 MySQL 8.0 升级后新建的使用的是 8.0 全新的默认排序规则utf8mb4_0900_ai_ci两个表的关联字段user_code VARCHAR(64)上明明都建了完美的二级索引然而当业务执行一句看似极其普通的二表关联时SELECT o.order_id, o.pay_amount FROM t_trade_order o JOIN t_user u ON o.user_code u.user_code WHERE o.order_id 8848;优化器却在底层挑选了一个对数千万行大表执行全表扫描All Table Scan的毁灭性物理计划单次查询耗时从 0.5ms 暴涨至 15 秒为什么看似完全相同的VARCHAR(64)字段仅仅因为排序规则的细微差异就会导致索引物理失效[字符集 / 排序规则不一致导致索引彻底失效微架构] t_trade_order 表 (utf8mb4_0900_ai_ci) ──▶ user_code 字段 (驱动表) │ ▼ (尝试关联被驱动表 t_user) t_user 表 (utf8mb4_general_ci) ──▶ user_code 字段上有 idx_user_code 索引! │ ▼ (由于 Collation 编码规则不同, 无法直接进行二进制逐字节比较!) ┌─────────────────────────────────────────────────────────────┐ │ MySQL 优化器被迫在底层注入隐式转换函数: │ │ ON CONVERT(u.user_code USING utf8mb4) COLLATE utf8mb4_0900_ai_ci o.user_code │ - ★ 致命物理后果: 索引列被包裹了函数调用! │ │ - B 树索引寻道彻底失效! 被迫退化为全表扫描 (5000 万行扫描!)│ └─────────────────────────────────────────────────────────────┘源码拆解为什么不同 Collation 无法直接走索引在 MySQL 优化器源码sql/item_cmpfunc.cc中内核在比对两个字符串操作数之前必须先进行字符集与排序规则强制对齐Coercibility Resolution排序权重的本质差异utf8mb4_general_ci采用的是简化的单字节查表排序速度快但对复杂重音字符处理粗糙utf8mb4_0900_ai_ci基于最新的Unicode 9.0 排序算法标准UCA支持重音不敏感Accent-Insensitive与大小写不敏感B 树的有序性依赖特定 Collationt_user表上的 B 树索引是按照utf8mb4_general_ci的规则排好序的当查询以utf8mb4_0900_ai_ci的标准传入参数时由于两者的排序大小定义不同B 树原有的二分查找逻辑彻底失效内核别无选择只能将整张表的每一行数据全部读入内存逐行执行转换函数后进行暴力比对-- 使用 EXPLAIN 查看隐式转换真实物理计划 EXPLAIN SELECT * FROM t_trade_order o JOIN t_user u ON o.user_code u.user_code; -- 在 WARNINGS 中会清晰打印出罪魁祸首: -- Cannot use index ... because of conversion: -- convert(u.user_code using utf8mb4) collate utf8mb4_0900_ai_ci生产级全库字符集标准化治理方案为了彻底根除此类隐患我们在大促后半场的治理中推行了全库字符集标准化改造-- 1. 生产级全库与全表 Collation 在线平滑统一为 MySQL 8.0 标准 ALTER TABLE t_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, ALGORITHM INPLACE, LOCK NONE; -- 2. 临时应急修复 SQL: 显式指定 COLLATE 消除隐式转换 SELECT o.order_id, o.pay_amount FROM t_trade_order o JOIN t_user u ON o.user_code (u.user_code COLLATE utf8mb4_0900_ai_ci) WHERE o.order_id 8848;CI/CD 静态扫描门禁在代码发布管道中配置自动化 AST 审查凡是参与JOIN关联的两个字段 Collation 不一致的 DDL一律自动拦截拒绝发布治理实战成效在完成全网 120 张核心历史表的 Collation 标准化统一后彻底消除了 35 处由于隐式字符集转换导致的慢查询全表扫描核心关联查询的平均耗时从850ms 骤降至 0.82ms提速超 1000 倍数据库 CPU 算力得到了极大释放从源头上抹平了跨版本升级带来的隐性性能陷阱。
返回列表