mysql 中 character set 与 collation 的点滴理解
Collation:即比对方法。用于指定数据集如何排序,以及字符串的比对规则。
每个 character set 会对应一定数量的 collation. 查看方法是在 mysql 的 console 下输入:
collation 名字的规则可以归纳为这两类:
1 2
|
<character set>_<language/other>_<ci/cs> <character set>_bin
|
例如:
utf8_danish_ci
ci
是
case insensitive
的缩写,
cs
是
case sensitive
的缩写。即,指定大小写是否敏感。
PS: 奇怪的是 utf8 字符集对应的 collation 居然没有一个是 cs 的。
那么
utf8_general_ci
,
utf8_unicode_ci
,
utf8_danish_ci
有什么区别?
他们各自存在的意义又是什么?
同一个 character set 的不同 collation 的区别在于
排序、字符串对比的准确度(相同两个字符在不同国家的语言中的排序规则可能是不同的)以及性能
。
例如:
utf8_general_ci
在排序的准确度上要逊于
utf8_unicode_ci
, 当然,对于英语用户应该没有什么区别。但性能上(排序以及比对速度)要略优于
utf8_unicode_ci
。 例如前者没有对德语中
ß = ss
的支持。而
utf8_danish_ci
相比
utf8_unicode_ci
增加了对丹麦语的特殊排序支持。
1、当表的
character set
是
latin1
时,若字段类型为
nvarchar
, 则字段的字符集自动变为
utf8
。
可见
database character set
,
table character set
,
field character set
可逐级覆盖。
2、在 ci 的 collation 下,如何在比对时区分大小写:
1 2 3 4
|
mysql> select * from pet where name = binary 'whistler';
mysql> select * from pet where binary name = 'whistler';
|
如上两条sql,查询结果应该是相同的,但是推荐使用前者,这样可以保证当前字段的索引依然有效, 而后者会使索引失效。
Mysql的row_format
1 2 3 4 5
|
CREATE TABLE `table_a` ( `a_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', ..... PRIMARY KEY (`a_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='demo表';
|
如上demo中,建表语句中有一项:
ROW_FORMAT=DYNAMIC
, 表示该表为动态表。
在 MySQL 中, 若一张表里面不存在
varchar
、
text
以及其变形、
blob
以及其变形的字段的话,那么张这个表其实也叫
静态表
,即该表的
row_format=fixed
,就是说每条记录所占用的字节一样。其优点读取快,缺点浪费额外一部分空间。
若一张表里面存在
varchar
、
text
以及其变形、
blob
以及其变形的字段的话,那么张这个表其实也叫
动态表
,即该表的
row_format=dynamic
,就是说每条记录所占用的字节是动态的。其优点节省空间,缺点增加读取的时间开销。
所以,做搜索查询量大的表一般都以空间来换取时间,设计成静态表。
关于 静态表和动态表,占用字节长度是动态还是静态的区别,可以查看后面提到的 varchar 和 char 的区别来理解。
row_format
还有其他一些值:
1 2 3 4 5 6
|
DEFAULT FIXED DYNAMIC COMPRESSED REDUNDANT COMPACT
|
修改行格式
1
|
ALTER TABLE table_name ROW_FORMAT = DEFAULT;
|
修改格式导致的结果:
1 2
|
fixed--->dynamic: 这会导致CHAR变成VARCHAR dynamic--->fixed: 这会导致VARCHAR变成CHAR
|