MySQL字符编码的讨论:如何处理emoji等4字节的Unicode字符-utf8mb4vs.utf8Collations(二)

2015-01-22 21:49:46 · 作者: · 浏览: 36
数据库写入异常。于是,就有两种解决方向:
1) 扔掉。
1.1) 扔掉或截断引发异常的字。采取此种方法,需要对每一个标题进行扫描。
1.2) 扔掉整条记录。可以采取扫描法,或者扔掉引发异常的记录。
2) 升级到utf8mb4。会略为降低数据库性能。

7.1. 性能考虑
首先对于写入性能,查找字体的性能损耗由于在写入前字符都已经变成编码,基本可以忽略。对于网络传输的性能,则需要继续查找相关资料继续查证。但初步估计由于目前数据库在本地,故此这部分开销的增长不太明显。
而对于索引的性能,由于网页标题这一字段没有做索引,在可预见的将来也未有此计划,故此没有性能的损耗,也没有升级兼容性的担心。
况且,倘若走扔掉数据的方向,若采取扫描法,则需要付出扫描的开销。若采取扔掉记录法,则会先触发事务回滚,其他记录需要下次重新写入。而且当一批记录写入时有k个记录引发异常,则需要回滚与重试k次,除非使用扫描法预先扫描出这些异常的记录。但这也会引入额外的程序与数据库开销。若不使用事务,则数据库总体写入性能会大为降低。
虽然没有实测过,但从感觉上来定性判断,似乎扔掉记录比升级collation带来的性能退化要大。

7.2. 存储空间考虑
当前的网页标题是使用VARCHAR2存储。对于现在可用的、常见的BMP字符,不会引入额外的存储开销。BMP字符在VARCHAR的类型下不会为每一字符引入额外33%的空间开销。反之,定长的CHAR就会引入这种额外开销。

7.3. 目标数据考虑
网页标题作为以后特征分析的数据源。在分析需求完全没有确定的情况下,我认为扔掉任何数据都是不宜采取的办法,特别是整条记录扔掉更是不推荐。因为现阶段我们没有一套标准去判定何为有效数据、何为无效数据。有可能引发异常的那部分数据确实是没用的数据,也有可能那部分人群更倾向于在我们平台上活跃使用。既然各种可能性都存在,我们主动放弃一部分可能性,似乎不太恰当。

7.4. API设计与兼容性考虑
由于utf8_unicode_ci与utf8mb4_unicode_ci都是使用UTF-8编码,所以对于JAVA,使用MyBatis生成的代码是一样的,都是使用String类型。这点已经实测过。加上这两种collations在BMP中的编码完全一致,所以使用3字节与4字节的系统,对于BMP中的字符都是完全兼容、正常显示的。而对于3字节的系统,4字节的字符一般会显示成一个方框,或者在一个方框中有几个小数字,不会引发系统异常。

8. 总结
诚然,emoji对分词分析目前来说还没有什么效果,粤语词而且在SIP中也只是其中一部分,也不知道有多少日本动漫或者爱情动作片的网页会遇到这些生僻字,音乐符号也少人用,太极符号也不是每次都出现,一些数学增补的字符与箭头增补图案也不是每个人都会用。这些加起来可能不知够不够全部的千分之一。
但是倘若每一两个小时就会由于字符不能写入,引发数据库的异常。通过上面的分析,我认为增加这种兼容性带来的成本是可以接受的。
故此,我建议使用升级的方法,兼容所有Unicode字符。