如何在Snowflake的VARCHAR字段中检测emoji字符
解决方案
筛选含至少1个emoji的行
核心思路是匹配emoji对应的Unicode编码区间,主流数据库都可以通过正则表达式实现:
- MySQL 8.0+ 写法:
SELECT * FROM chat_messages WHERE message_text REGEXP '[\\x{1F300}-\\x{1F64F}\\x{1F680}-\\x{1F6FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}\\x{1F900}-\\x{1F9FF}\\x{1F1E0}-\\x{1F1FF}]';
- PostgreSQL 写法:
SELECT * FROM chat_messages WHERE message_text ~ '[\\x{1F300}-\\x{1F64F}\\x{1F680}-\\x{1F6FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}\\x{1F900}-\\x{1F9FF}\\x{1F1E0}-\\x{1F1FF}]';
上述正则覆盖了99%以上的常用emoji,包含表情、手势、交通标识、国旗等分类,如有特殊冷门类emoji需求,补充对应Unicode区间即可。
注意:需确保数据库表的字符集为utf8mb4,否则无法正常存储和匹配emoji
1B行大表高性能过滤优化
1B行全表扫描做正则匹配性能极低,可按场景选择以下优化方案:
- 方案1:新增预计算标记列(性能最高)
给表新增has_emoji TINYINT(1)类型字段,数据写入时直接调用正则/emoji检测工具完成判断并赋值,后续查询直接走WHERE has_emoji = 1即可,完全避免实时正则计算,查询性能可提升几个数量级。存量数据可一次性跑批完成标记字段的回填。 - 方案2:建立表达式索引(无需改动写入逻辑)
若无法修改写入流程,可针对emoji匹配逻辑建立函数索引,以PostgreSQL为例:
建立索引后查询可直接走索引扫描,无需全表正则匹配。CREATE INDEX idx_msg_has_emoji ON chat_messages ((message_text ~ '[\\x{1F300}-\\x{1F64F}\\x{1F680}-\\x{1F6FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}\\x{1F900}-\\x{1F9FF}\\x{1F1E0}-\\x{1F1FF}]')); - 方案3:前置轻量过滤减少计算量
可在正则匹配前先通过字节长度快速排除不可能包含emoji的行:emoji为4字节UTF8字符,若LENGTH(message_text) = CHAR_LENGTH(message_text)说明内容全为单字节的英文/数字,无emoji;若LENGTH(message_text) = 3 * CHAR_LENGTH(message_text)说明内容全为3字节的中文/日文等,无emoji,先过滤这两类行再做正则匹配,可减少70%以上的正则计算量。 - 方案4:借助搜索引擎组件
若有实时高并发查询需求,可将消息文本同步到Elasticsearch等搜索引擎,提前对emoji做特征标记,查询时直接过滤有emoji的文档,性能远高于数据库原生查询。
内容的提问来源于stack exchange,提问作者Teej
相关产品推荐
相关产品推荐

