MySQL 字符集相关
为了支持各个国家的不同语言,MySQL 从4.0 版本开始支持了很多种字符集,且每种字符集支持了 N 多种排序规则。我们可以在建表的时候指定字符集的排序规则,不指定时会有一个默认规则。
字符集和排序规则总是一起使用的,每个排序规则都是针对某个特性的字符集,和其他字符集没有关系。
只有基于 字符串 的值才有 字符集 的概念。其他类型的值,像 int,float,bool 字符集的配置只是一种声明。
每个 database 有自己的字符集和排序规则默认值,每张表可以指定自己的字符集和排序规则,同一张表的不同字段也可以指定自己的字符集和排序规则。这是一个逐层继承的默认设置。
查看 MySQL 支持的字符集
show charset 命令可以查看当前版本支持哪些字符集
mysql> show charset;
+----------+---------------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| binary | Binary pseudo charset | binary | 1 |
Charset:支持的字符集
Default collation:默认排序规则。常用的规则( _ci 结尾表示大小写不敏感;_cs 结尾表示大小写敏感;_bin 表示二进制的比较 )
Maxlen:最大支持的字节数
show collation 查看字符集支持的哪些排序规则
mysql> show collation like 'gbk%';
+----------------+---------+----+---------+----------+---------+---------------+
| Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
+----------------+---------+----+---------+----------+---------+---------------+
| gbk_bin | gbk | 87 | | Yes | 1 | PAD SPACE |
| gbk_chinese_ci | gbk | 28 | Yes | Yes | 1 | PAD SPACE |
+----------------+---------+----+---------+----------+---------+---------------+
2 rows in set (0.02 sec)
配置字符集和排序规则
在 my.cnf 文件中配置默认字符集
> cat my.cnf
[client] # 客户端连接时的字符集
default-character-set = utf8mb4
[mysql] # mysql shell 登录时的字符集
default-character-set = utf8mb4
[mysqld] # 服务端字符集
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci # 排序规则
在 session 会话中配置字符集
执行 status 命令查看当前会话的字符集
mysql> status
--------------
...
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
...
修改 当前会话的字符集
mysql> set NAMES "utf8";
Query OK, 0 rows affected, 1 warning (0.03 sec)
mysql> status
--------------
...
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb3 # 只能修改会话参数,而没有修改服务端。
Conn. characterset: utf8mb3
...
建表的时候配置字符集
a 列指定了 gbk 字符集,排序规则默认
b 列指定了 utf8 字符集,排序规则是 utf8mb4_general_ci
c 列字符集和排序规则都是表 t4 的默认值 (CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci)
这是一个逐层继承的默认设置,但通常不需要这么配置。
mysql> CREATE TABLE t4 (
a VARCHAR(2) CHARSET GBK,
b VARCHAR(4) CHARSET UTF8 COLLATE UTF8_GENERAL_CI,
c VARCHAR(6)
);
mysql> show create table t4 \G;
Create Table: CREATE TABLE t4 (
a varchar(2) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
b varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
c varchar(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1. 隐式转换之字符集
只有字符集相同的字段才能做比较运算,如果字符集不同,MySQL 会先将其准换成同一个字符集再进行比较。(如果两个字符集不兼容的话则报错)
接上面的例子 表t4:
mysql> show full columns from t4;
+-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| a | varchar(2) | gbk_chinese_ci | YES | | NULL | | select,insert,update,references | |
| b | varchar(4) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| c | varchar(6) | utf8_unicode_ci | YES | | NULL | | select,insert,update,references | |
+-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
插入一些测试数据:
insert into t4 select "跑步","跑步","ff";
insert into t4 select "aa","aa","cc";
insert into t4 select "aa","bb","dd";
mysql> select * from t4;
+--------+--------+------+
| a | b | c |
+--------+--------+------+
| 跑步 | 跑步 | ff |
| aa | aa | cc |
| aa | bb | dd |
+--------+--------+------+
a, b 字段比较测试:
mysql> select t4.*, if(a=b,"a==b","a!=b") ret from t4 where c="ff";
+--------+--------+------+------+
| a | b | c | ret |
+--------+--------+------+------+
| 跑步 | 跑步 | ff | a==b |
+--------+--------+------+------+
a, b 列是不同的字符集。 gbk 存中文字符 占两个字节,utf8 是三个字节,存储方式不同,显然不能直接比较。但测试结果返回 True。这是因为优化器帮我们隐式类型转换了。
可以 trace 验证一下:( trace 分析器可以追踪到优化器具体是如何执行 sql,和选择执行计划的 )
mysql> set optimizer_trace='enabled=on',end_markers_in_json=on; # 开启trace分析器会对 MySQL 性能有所影响,建议只在 优化分析问题时临时开启。
mysql> select * from information_schema.optimizer_trace \G; # 查看分析结果
*************************** 1. row ***************************
QUERY: select t4.*, if(a=b,"a==b","a!=b") ret from t4 where c="ff"
TRACE: {
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `t4`.`a` AS `a`,`t4`.`b` AS `b`,`t4`.`c` AS `c`,if((convert(`t4`.`a` using utf8) = `t4`.`b`),'a==b','a!=b') AS `ret` from `t4` where (`t4`.`c` = 'ff')"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`t4`.`c` = 'ff')",
...
优化器用 convert() 函数,把 gbk 转成了 utf8,然后再对比:
expanded_query": "/* select#1 */ select `t4`.`a` AS `a`,`t4`.`b` AS `b`,`t4`.`c` AS `c`,if((convert(`t4`.`a` using utf8) = `t4`.`b`)
2. 字符集使用时的一些其他问题
- join 关联查询时,被关联的列,如果是不同的字符集,那么关联的列会有索引失效的情况。
- 影响大小写字符的比较 utf8 默认的排序规则是 _ci 时 ,也就是大小写不敏感,那么查询的时候 select * from t where c1="a",会同时返回 c1="a" 和 c1="A"
和预期的结果不一致。敏感还是不敏感要视业务需求而定。- 在大小写不敏感的列上创建唯一索引时,可能会失败,因为可能会出现重复的列值,建索引时 Btree 需要先对列值比较排序。
- 不同的字符集校对规则之间的转换会带来额外的系统开销,性能会有下降。
MySQL 字符集相关的更多相关文章
- RDS For MySQL 字符集相关说明
https://help.aliyun.com/knowledge_detail/41706.html?spm=5176.7841698.2.9.F5YjI5 字符序命名规则 字符集相关 MySQL ...
- 从一个慢查询到MySQL字符集编码
从一个慢查询到MySQL字符集编码 目录 从一个慢查询到MySQL字符集编码 1. 问题起源 2. MySQL字符集和字符集排序规则 2.1 字符集相关概念 2.2 MySQL中的字符集和字符集排序规 ...
- MySQL字符集编码相关
Windows 10家庭中文版,MySQL 5.7.20,2018-05-07 Part.1 查找数据库的字符集编码 查看MySQL字符集编码:status命令 使用命令行登录MySQL服务器,然后 ...
- Mysql字符集设置
转 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等:• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encodi ...
- MySQL字符集
字符集的选择 1.如果数据库只需要支持中文,数据量很大,性能要求也很高,应该选择双字节定长编码的中文字符集(如GBK).因为相对于UTF-8而言,GBK"较小",每个汉字只占2个字 ...
- Mysql字符集知识总结
字符集&字符编码方式 字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,这里的字符可以是英文字符,汉字字符,或者其他国家语言字符. 常见字符集 ...
- MySQL字符集转换引发插入乱码问题
根据http://www.cnblogs.com/cchust/p/4601536.html进行验证测试 问题背景 在mysql上面执行一条普通的insert语句,结果报错: Incorrect st ...
- [MySQL] 字符集的选择
1. Mysql支持的字符集 MySQL服务器可以支持多种字符集,不同的字段都可以使用不同的字符集. 查看所有可用字符集: show character set; select * from info ...
- Mysql优化相关总结
Mysql优化相关总结 2016-05-31 数据库集中营 优化顺序: 选择适当的引擎和表结构和数据类型 建立索引,优化sql. 增加缓存,redis.memcache. 主从.主主,读写分离. my ...
随机推荐
- Express中使用session
1.安装express-session npm install express-session --save-dev //注意-g无效 2.app.jsvar session = require('e ...
- Redis 源码简洁剖析 12 - 一条命令的处理过程
命令的处理过程 Redis server 和一个客户端建立连接后,会在事件驱动框架中注册可读事件--客户端的命令请求.命令处理对应 4 个阶段: 命令读取:对应 readQueryFromClient ...
- Netty核心原理
Netty核心原理 1. Netty介绍 1.1 原生NIO存在的问题 NIO的类库和API使用繁杂 需要具备其他额外的技能,如java多线程编程等才能编写出高质量的NIO程序 开发工作量和难度都非常 ...
- 《手把手教你》系列技巧篇(六十七)-java+ selenium自动化测试 - 读写excel文件 - 中篇(详细教程)
1.简介 前面介绍了POI可以操作excel,也简单的提到另一个操作excle的工具,本篇介绍一个其他的可以操作excel的工具,但是这个工具有一个前提,excel文件版本只能是97-2003版本,如 ...
- STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率
前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...
- ssh 主机之间免密配置脚本
文章目录 单向免密 `expect` 免交互 `sshpass` 免交互 相互免密 单向免密 expect 免交互 注意修改脚本内的 your_password 为 远程主机用户的密码 脚本内的 &q ...
- Ribbon负载均衡及其应用
nginx - 随笔分类 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中涉及到负载均衡,为何此处由涉及Ribbon负载均衡呢?那是因为ngnix是服务端的负责均衡,而Ribbon是客户 ...
- 树莓派PICO刷入MicroPython内核的两种方式
一.MicroPython简介 MicroPython 是 Python 3编程语言的精简高效实现,其中包括 Python 标准库的一小部分,并且经过优化,可在微控制器和受限环境中运行. 可以在 25 ...
- 提名者周训,misc消失的文件
下载附件是一个没有后缀的文件,一般这种东西,根据我这个菜狗的经验,直接就是丢进kali的binwalk一顿操作,最后果不其然,是发现了东西的 这里面可以看到一个小细节,就是在binwalk进行分离的时 ...
- ASP.NET Core 6框架揭秘实例演示[14]:日志的进阶用法
为了对各种日志框架进行整合,微软创建了一个用来提供统一的日志编程模式的日志框架.<日志的基本编程模式>以实例演示的方式介绍了日志的基本编程模式,现在我们来补充几种"进阶" ...