• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

MySQL字符集和copy_and_convert_MySQL

mysql 搞代码 4年前 (2022-01-09) 20次浏览 已收录 0个评论

gaodaima.com

MySQL字符集和copy_and_convert

关于copy_and_convert

在对MySQL做业务压力测试的时候,我们在perf结果中发现 copy_and_convert 是一个耗费cpu的操作。这个函数的意思,就是在字符集之间做内容转换。

如果源和目标的字符集相同,就可以直接用memcpy,这显然比做字符集转换(按字节或字长拷贝更快,和节省cpu)

当整个系统是CPU瓶颈时,我们希望能够减少这种cpu消耗。

一次查询涉及的拷贝

如果我们执行一个简单的select语句,会涉及到两部分的内容:metadata和data。MySQL的返回包是能够“自解析”的,也就是说不仅有内容,还有描述信息。这些描述信息我们称为metadata。

在将这两部分信息返回给客户端的时候,就涉及到字符串拷贝,如果源字符集和目标字符集不同,就需要作转换。

字符集里面可以定义的部分

1、 表的字符集

比如我们创建如下的表

CREATE TABLE `t` (

`c` int(11) DEFAULT NULL,

`d` varchar(50) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=gbk;

这就定义了这个表的字符集,要求存入数据按照gbk格式存储。在我们查询的时候,从表中读出的数据,就是我们上文说到的“源字符集”,在这里是gbk.

比如

Insert t values(2012, ‘南方很冷’);

2、连接字符集

在连接的时候我们可以在mysql客户端指定参数 mysql -default-character-set=gbk ,表示我们接收的内容希望是gbk编码,这个就是上文说的“目标字符集”。

一般我们会被建议:连接字符集和表字符集相同。

有的文章说防止乱码—-乱码倒是不会,实际的原因就是在内容拷贝时避免字符集转换计算。

本文要说的“但是”

但是即使这么做,在压力测试(或者你gdb)时,还是会发现会调用到 copy_and_convert。

原因有二:

首先,metadata部分,是固定的使用utf8,这个值可以从show variables like ‘character_set_system’;的结果看到,hardcode,配置无法修改。

其次,虽然我们定义表字符集是gbk, 但是整型字段是是Latin1存储,

#define my_charset_numeric my_charset_latin1,配置无法修改。

因此在我们上面的设置中,一次查询,在传回metadata的时候需要utf8->gbk, 返回结果中c这个字段需要latin1->gbk.

问题和建议

从上面分析知道,这存在的问题就是,无论用户怎么设置,都无法完全避免这种转换。

由于数字类型转成字符串后,使用什么字符集都占用一样的空间。

1) 在代码上最简单的修改可以如下:

将 #define my_charset_numeric my_charset_latin1 改成

#define my_charset_numeric my_charset_utf8_general_ci

这样跟metadata部分相同,然后建表和

本文来源gaodai.ma#com搞#代!码(网

客户端都是使用utf-8。

2) 更灵活一点是把character_set_system改成可配置,然后整型存储按照用户定义的字符集。

gaodaima.com


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:MySQL字符集和copy_and_convert_MySQL

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址