utf8mb4_0900_ai_ciutf8mb4_unicode_ci 都是有效的 UTF-8 字符集排序规则,但它们有一些重要区别:

主要差异

1. Unicode 版本支持

2. 排序准确性

utf8mb4_0900_ai_ci 对某些语言的排序更准确,特别是:

3. 性能

4. AI 和 AS 的含义

潜在问题

⚠️ 最主要的问题:跨表 JOIN 和比较

如果 soe_data 表使用 utf8mb4_0900_ai_ci,而 dispatch_logs 表使用 utf8mb4_unicode_ci,可能会遇到:

-- 这种 JOIN 可能会有警告或性能问题
SELECT * 
FROM dispatch_logs d
JOIN soe_data s ON d.equipment_name = s.dev_name
-- 两个表的 collation 不同

MySQL 的处理方式:

示例:字符匹配差异

-- utf8mb4_unicode_ci 下
'café' = 'cafe'  -- false

-- utf8mb4_0900_ai_ci 下(accent insensitive)
'café' = 'cafe'  -- true (不区分重音)

建议方案

方案1:统一 Collation(推荐)

-- 将 soe_data 改为与 dispatch_logs 一致
ALTER TABLE soe_data 
CONVERT TO CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

方案2:在查询中显式指定 Collation

# 在 Perl 代码中的 SQL 查询
my $sql = "SELECT d.*, s.* 
           FROM dispatch_logs d
           JOIN soe_data s 
           ON d.equipment_name COLLATE utf8mb4_unicode_ci = 
              s.dev_name COLLATE utf8mb4_unicode_ci";

方案3:保持现状(如果符合条件)

可以不改的情况:

对现有代码的影响

查看你的 Feeder3568.pm 模块:

# 当前代码中,两表是独立查询的,没有 JOIN
sub _ingest_dispatch_logs { ... }  # 查询 dispatch_logs
sub _ingest_soe_data { ... }       # 查询 soe_data

好消息: 你的代码中两表是分别查询的,没有直接 JOIN,所以影响较小。

但需要注意:
如果设备名称包含特殊字符(如中文、重音字符),不同的 collation 可能导致:

# dispatch_logs 中的设备名
"10kV某某线"

# soe_data 中的设备名  
"10kV某某线"  # 看起来一样,但可能因 collation 不同匹配不上

最终建议

立即检查:

-- 查看 dispatch_logs 的 collation
SHOW CREATE TABLE dispatch_logs;

-- 如果它是 utf8mb4_unicode_ci,建议统一
ALTER TABLE soe_data 
CONVERT TO CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

如果暂时不能修改表结构:
在代码中添加注释标记这个潜在问题,便于后续排查:

# Note: soe_data uses utf8mb4_0900_ai_ci while dispatch_logs uses utf8mb4_unicode_ci
# This may cause issues if tables are joined in the future
# Consider unifying collations if data matching problems occur

对于电网设备名称这种场景,统一使用 utf8mb4_unicode_ci 是更安全的选择,因为它兼容性更好,且 MySQL 5.7+ 都支持。