竹永康在科锐待岗第2天工作总结

领导今日未给我分配工作任务,我利用空闲时间研读了《高性能MySQL》一书中的第七章第9节:MySQL高级特性之MySQL中如何使用字符集,从中学习到了一些专业技能知识。总结如下:

MySQL中如何使用字符集

只有基于字符的值才真正的“有”字符集的概念。对于其它类型的值,字符集只是一个设置,指定用哪一种字符集来做比较或者其它操作。基于字符的值能存放咋某列中、查询的字符串中、表达式的计算结果中或者用户的某个变量中,等等。

关于字符集,MySQL的设置可以分两类:创建对象时的默认设置;在服务器和客户端通信时的设置。

创建对象时的默认配置

MySQL服务器有默认的字符集和校对规则;每个库也有自己的默认值;每个表也有自己的默认值(甚至表中不同的字段也可以指定不同的字符集)。这是一个逐层继承的默认设置,最终最靠底层的默认设置将影响你创建的对象。在这个“阶梯”的每一层,都可以指定一个特定的字符集或者让服务器使用它的默认值:

  • 创建库的时候,将根据服务器上的 character_set_server 设置来设定该库的默认字符集;
  • 创建表的时候,将根据库的字符集设置来指定这个表的字符集设置;
  • 创建列的时候,将根据表的设置指定列的字符集设置。

一个表的默认字符集设置无法影响存储在这个表中某个列的值。只有在创建列而没有为列指定字符集的时候,表的默认字符集才有用。

服务器和客户端通信时的设置

当服务器和客户端通信的时候,它们可能使用不同的字符集。这时,服务器端将进行必要的翻译转换工作:

  • 服务器总是假设客户端是按照 character_set_client 设置的字符来传输数据和SQL语句的;
  • 当服务器收到客户端的SQL语句时,它先将其转换成字符集 character_set_connection。它还使用这个设置来决定如何将数据转换成字符串;
  • 当服务端返回数据或者错误信息给客户端时,它会将其转换成 character_set_result。

MySQL如何比较两个字符串的大小

如果比较的两个字符串的字符集不同,MySQL会先将其转换成同一个字符集再进行比较。如果两个字符集不兼容的话,则会抛出错误,这种情况下需要通过函数 CONVERT() 显式地将其中一个字符串的字符集转换成一个兼容的字符集(在高版本的MySQL中会自动做隐式转换)。

还可以使用下划线前缀 “_” 以及 COLLATE 子句来指定字符串的字符集和校对规则,示例语句:

SELECT _utf8 'hello world' COLLATE utf8_bin;

一些特殊的情况

  • character_set_database 设置的默认值和默认数据库的设置相同。当改变默认数据库的时候,这个变量也会跟着变;
  • 当使用 LOAD DATA INFILE 的时候,数据库总是将文件中的字符按照字符集 character_set_database 来解析;
  • MySQL在加载数据的时候,总是以同样的字符集处理所有数据,而不管表中的列是否有不同的字符集设定;
  • MySQL会将 SELECT INTO OUTFILE 的结果不做任何转码的写入文件(目前除了使用 CONVERT() 函数主动转码外,还没有什么其它办法);
  • MySQL始终会根据 character_set_client 的设置来解析转义符号,即使查询中指定了别的字符集。

如何选择字符集和校对规则

先为服务器和库选择一个合理的、全局通用的字符集,在根据实际情况给某个列选择合适的字符集。

字符集和校对规则如何影响查询

某些字符集和校对规则可能会需要更多的CPU操作,可能会消耗更多的内存和存储空间,甚至还会影响索引的正常使用。不同字符集和校对规则之间的转换可能会带来额外的开销。只有排序查询要求的字符集与服务器数据库的字符集相同的时候,才能使用索引进行排序。

MySQL会在需要的时候进行字符集转换。例如当使用两个字符集不同的列来关联两个表的时候,MySQL会尝试转换其中一个列的字符集。这和在数据列外面封装一个函数一样,会让MySQL无法使用这个列上的索引。

注意在多字节字符集中,一个字符不再是一个字节。例如 utf8 字符集的一个字符占3个字节。以及如果要索引一个 utf8 字符集的列,MySQL会假设每一个字符都是3个字节,所以最长索引前缀的限制一下就缩短到原来的三分之一(333个字符)。这会对MySQL使用索引有一些影响,例如将无法对此列使用索引覆盖扫描。

你可能感兴趣的:(mysql)