mysql如何处理字符集导致索引失效_mysql连接排序规则一致性

2次阅读

mysql如何处理字符集导致索引失效_mysql连接排序规则一致性

mysql 字符集不一致直接让索引失效

只要 WHERE 条件里涉及的列、参数、连接表字段三者字符集或排序规则(COLLATION)不完全一致,MySQL 就可能放弃使用索引,哪怕该列明明建了索引。这不是 bug,是设计行为——比较前必须隐式转换,而转换后无法走索引。

查清当前字段和连接参数的排序规则

别猜,用 SQL 直接看。最常出问题的是 utf8mb4_general_ciutf8mb4_0900_as_cs 混用,或者客户端连接时没指定 collation_connection

  • 查字段排序规则:SHOW FULL COLUMNS FROM table_name LIKE 'col_name';
  • 查连接当前排序规则:select @@collation_connection, @@character_set_client;
  • 查表默认排序规则:SHOW CREATE TABLE table_name;

JOIN 时两边字段 COLLATION 不匹配导致全表扫描

比如左表字段是 utf8mb4_0900_as_cs,右表同名字段是 utf8mb4_unicode_ci,即使类型都是 VARCHAR,MySQL 也会拒绝用索引做等值连接,改走 Block Nested-Loop。

  • 强制统一两边字段的 COLLATE:在 ONWHERE 中显式加 COLLATE utf8mb4_0900_as_cs
  • 但更稳妥的做法是修改字段本身:ALTER TABLE t MODIFY col VARCHAR(255) COLLATE utf8mb4_0900_as_cs;
  • 注意:修改字段 COLLATION 可能触发表重建,大表慎操作;且 utf8mb4_unicode_ci 在 8.0+ 已被标记为 deprecated

客户端连接未声明 COLLATION 导致隐式转换

Java 的 mysql-connector-java 默认不传 collationConnection,PHP 的 mysqli 如果没调用 set_charset(),都可能导致传入的字符串按服务端默认(如 latin1_swedish_ci)解析,跟字段 COLLATION 不符。

  • 连接串里加参数:?useUnicode=true&characterEncoding=utf8mb4&collationConnection=utf8mb4_0900_as_cs
  • 连接后立刻执行:SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_cs;
  • 验证是否生效:SELECT CHARSET('测试'), COLLATION('测试'); —— 返回应与字段一致

字符集问题不是“有没有”,而是“哪一层不一致”。连错一层,索引就掉一层。最麻烦的是它不报错,只悄悄变慢,查 EXPLAIN 里的 keyrows 才能发现异常。

text=ZqhQzanResources