【MySQL系列】深入理解MySQL中的存储、排序字符集

image

前言

  在创建数据库时,我们经常会需要填写数据库的所用字符集、排序规则,字符集和排序规则是两个非常重要的概念,它们决定了数据库如何存储和比较字符串数据。在 MySQL 中,常用的存储字符集有 utf8、utf8mb4,而排序字符集有 utf8mb4_unicode_ci、utf8mb4_general_ci、utf8mb4_bin、utf8mb4_0900_ai_ci,如下图所示。今天我们来探讨一下MySQL中几种常用的字符集和排序规则之间的区别和适用场景。

image

一、存储字符集

  utf8mb4 和 utf8 是 MySQL 中两种常用的字符集,它们都可以用来存储 Unicode 字符,但是有一些区别和联系。接下来,我们将从以下几个方面对比 utf8mb4 和 utf8。

1.1 字符集简介

  utf8 是 Mysql 中最早支持的 Unicode 字符集,是一种可变长度的字符编码方式,可以表示世界上几乎所有的字符。它使用 1 到 3 个字节的 UTF-8 字符,具体取决于字符的编码范围。

  要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持。个人觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8。

1.2 区别详解

  • 编码范围
    • UTF-8 可以表示大多数常见的字符,但对于一些罕见的字符和 emoji 表情等,可能无法正确表示。这些字符需要 4 个字节来编码,所以 utf8 会在遇到这些字符时报错或者出现乱码。
    • utf8mb4 则可以表示几乎所有的 Unicode 字符,能够存储 Emoji 表情、部分罕用汉字、新增的 Unicode 字符等。
  • 存储需求
    • 由于 utf8mb4 可以表示更多的字符,所以它通常需要比 UTF-8 更多的存储空间。具体来说,UTF8MB4 可能需要使用 1 到 4 个字节来表示一个字符,而 UTF-8 通常只需要使用 1 到 3 个字节。
    • 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。例如,一个 CHAR(10) 类型的字段,如果使用 utf8 字符集,那么它需要保留 10 * 3 = 30 个字节的空间。如果使用 utf8mb4 字符集,那么它需要保留 10 * 4 = 40 个字节的空间。
    • 对于 VARCHAR 类型的字段,如果使用 utf8 字符集,那么它需要额外使用一个字节来记录字符串的长度。如果使用 utf8mb4 字符集,那么它需要额外使用两个字节来记录字符串的长度。
  • 兼容性
    • UTF-8 是一种广泛使用的字符集,几乎所有的操作系统和编程语言都支持它。因此,如果需要与其他系统进行数据交换,UTF-8 可能是一个更好的选择。
    • 如果需要支持更广泛的字符范围,或者需要更高的安全性和兼容性,那么应该使用 utf8mb4 字符集。utf8mb4 虽然可以表示更多的字符,但并不是所有的系统都支持它。在使用 utf8mb4 时,需要确保应用程序和数据库服务器都支持这个字符集。

1.3 选择建议

  • 如果应用程序只需要处理常见的字符,那么 UTF-8 可能是一个不错的选择,它具有广泛的兼容性和较低的存储需求。
  • 如果应用程序需要处理一些罕见的字符或 emoji 表情等,那么 utf8mb4 可能是更好的选择,它可以确保数据能够正确地存储和显示所有的字符。
  • 在选择字符集时,还需要考虑数据库的性能和存储需求。如果数据库中存储了大量的文本数据,那么选择一个合适的字符集可以提高数据库的性能和存储效率

  总之,UTF-8 和 utf8mb4 都是 MySQL 中常用的字符集选项,都可以用来存储 Unicode 字符,它们之间的区别主要在于编码范围、存储需求和兼容性。在选择字符集时,需要根据应用程序的具体业务需求和实际情况来进行选择,以确保数据能够正确地存储和显示。虽然,utf8mb4 比 utf8 需要更多的存储空间,并且在某些情况下可能会导致性能略有下降。不过在现代硬件和应用场景下,utf8mb4 的性能影响通常可以忽略不计。

二、排序规则

2.1 排序规则概述

  排序规则是指在比较和排序字符串时所遵循的规则,用于定义字符的排序和比较方式,而排序规则会影响字符串的比较、排序等操作。不同的字符集可以有不同的排序规则,甚至同一个字符集也可以有多种排序规则。在 MySQL中,比较常用的字符集是utf8和utf8mb4,这两个字符集是类似的,查看下 utf8mb4 字符集下支持的所有比较规则:

SHOW COLLATION LIKE 'utf8\_%';
SHOW COLLATION LIKE 'utf8mb4\_%';
Collation(排序方式)Charset(字符集)IdDefault(默认值)CompiledSortlen(排序)
utf8mb4_general_ciutf8mb445YesYes1
utf8mb4_binutf8mb446Yes1
utf8mb4_unicode_ciutf8mb4224Yes8
utf8mb4_icelandic_ciutf8mb4225Yes8
utf8mb4_latvian_ciutf8mb4226Yes8
utf8mb4_romanian_ciutf8mb4227Yes8
utf8mb4_slovenian_ciutf8mb4228Yes8
utf8mb4_polish_ciutf8mb4229Yes8
utf8mb4_estonian_ciutf8mb4230Yes8
utf8mb4_spanish_ciutf8mb4231Yes8
utf8mb4_swedish_ciutf8mb4232Yes8
utf8mb4_turkish_ciutf8mb4233Yes8
utf8mb4_czech_ciutf8mb4234Yes8
utf8mb4_danish_ciutf8mb4235Yes8
utf8mb4_lithuanian_ciutf8mb4236Yes8
utf8mb4_slovak_ciutf8mb4237Yes8
utf8mb4_spanish2_ciutf8mb4238Yes8
utf8mb4_roman_ciutf8mb4239Yes8
utf8mb4_persian_ciutf8mb4240Yes8
utf8mb4_esperanto_ciutf8mb4241Yes8
utf8mb4_hungarian_ciutf8mb4242Yes8
utf8mb4_sinhala_ciutf8mb4243Yes8
utf8mb4_german2_ciutf8mb4244Yes8
utf8mb4_croatian_ciutf8mb4245Yes8
utf8mb4_unicode_520_ciutf8mb4246Yes8
utf8mb4_vietnamese_ciutf8mb4247Yes8

  这些比较规则的命名还挺有规律的,具体规律如下:

  • 比较规则名称以与其关联的字符集的名称开头,如上述查询结果的比较规则名称都是以utf8mb4开头的。

  • 后边紧跟着该比较规则主要作用于哪种语言,比如 utf8_polish_ci 表示以波兰语的规则比较,utf8_spanish_ci 是以西班牙语的规则比较,utf8_general_ci 是一种通用的比较规则。

  • 名称后缀意味着该比较规则是否区分语言中的重音、大小写啥的,具体可以用的值如下:

    后缀英文释义描述
    _aiaccent insensitive不区分重音。也就是说,排序时 e、è、é、ê 和 ë 之间没有区别。
    _asaccent sensitive区分重音。
    _cicase insensitive不区分大小写,即 “大小写不敏感”。
    _cscase sensitive区分大小写,即大小写敏感。
    _binbinary以二进制方式比较,区分大小写和重音符号。

  比如 utf8mb4_general_ci 这个比较规则是以 ci 结尾的,说明不区分大小写。每种字符集都有一种默认的比较规则,SHOW COLLATION 返回结果中的Default 列的值为 YES 的就是该字符集的默认比较规则,比如 utf8mb4 字符集默认规则就是utf8mb4_general_ci,又比如utf8字符集默认规则就是 utf8_general_ci。排序规则的不同会影响字符串的比较和排序的结果,进而影响索引的效率和查询的性能。一般来说,_bin 排序规则的性能最高,因为它只需要按照二进制方式比较字符串,不需要考虑字符的大小写和重音符号等因素。_general_ci 排序规则的性能次之,因为它只需要按照一般方式比较字符串,不需要考虑字符的语言或地区等因素。_unicode_ci 和 _ci 排序规则的性能最低,因为它们需要按照 Unicode 标准或特定语言或地区的方式比较字符串,需要考虑字符的大小写和重音符号等因素。

2.2 比较规则

  比较规则可以作用于四个级别,分别是服务器级别、数据库级别、表级别、列级别。服务器级别的比较规则由collation_server参数控制,如果创建数据库、表、列时没有显式的指定比较规则,则会继承上一级的比较规则。下面给出创建及修改库、表、列的比较规则的示例语句:

-- 创建数据库指定比较规则
CREATE DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];-- 修改数据库的比较规则
ALTER DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];-- 创建表时指定比较规则
CREATE TABLE 表名 (列的信息)[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]]-- 修改表的比较规则
ALTER TABLE 表名[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]# 创建时指定列的比较规则
CREATE TABLE 表名(列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],其他列...
);-- 修改列的比较规则
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];

2.3 排序字符集

  utf8 字符集默认规则是 utf8_general_ci,常用到的有utf8_general_ci、utf8_unicode_ci、utf8_bin等。而 utf8mb4 字符集默认规则是utf8mb4_general_ci,常用到的有utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_bin等,其他比较规则基本很少会用,下面简单了解下这几种规则的异同。

utf8_bin、utf8mb4_bin

  将字符串每个字符用二进制数据编译存储,区分大小写,也区分重音符号。_bin 的比较方法其实就是直接将所有字符看作二进制串,然后从最高位往最低位比对,所以很显然它是区分大小写的。

utf8_general_ci、utf8mb4_general_ci

  utf8_general_ci 是 utf8 字符集的一种排序规则,不区分大小写,也不区分重音符号。utf8mb4_general_ci 是utf8字符集的一种排序规则,不支持扩展,它仅能够在字符之间进行逐个比较,不区分大小写,但会区分重音符号。utf8_general_ci 校对规则进行的比较速度很快,但是与使用 utf8mb4_unicode_ci 的校对规则相比,比较正确性较差。

注意:utf8mb4_general_ci 与 utf8_general_ci 基本兼容,只是前者支持更多字符。

utf8_unicode_ci、utf8mb4_unicode_ci

  是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

utf8mb4_0900_ai_ci

  MySQL 8.0 默认的是 utf8mb4_0900_ai_ci,属于 utf8mb4_unicode_ci 中的一种。

  以前,utf8mb4_general_ci 是默认排序规则。由于 utf8mb4_0900_ai_ci 排序规则现在是默认排序规则,因此默认情况下新表格可以存储基本多语言平面之外的字符。现在可以默认存储表情符号。如果需要重音灵敏度和区分大小写,则可以使用 utf8mb4_0900_as_cs 代替。

三、附录

3.1 utf8mb4_unicode_ci 和 utf8mb4_general_ci 的区别

  • 准确性

    排序字符集说明
    utf8mb4_unicode_ci是基于标准的 Unicode 来排序和比较,能够在各种语言之间精确排序。
    utf8mb4_general_ci没有实现 Unicode 排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。

    注意:在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

  • 性能

    排序字符集说明
    utf8mb4_general_ci在比较和排序的时候更快。
    utf8mb4_unicode_ci在特殊情况下,Unicode 排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

    注意:在绝大多数情况下,不会发生此类复杂比较。

3.2 实践建议

在开发时,个人建议:

  • 尽可能使用 utf8mb4 字符集,以确保能够支持完整的 Unicode 字符集。
  • 根据具体需求选择合适的排序规则,大多数情况下可以使用 utf8mb4_general_ci
  • 在创建表和列时就指定字符集和排序规则,避免以后出现编码问题。
  • 如果需要存储大小写或重音符号敏感的数据,使用 utf8mb4_bin 排序规则。
  • 对于加密数据或需要按二进制方式比较的场景,也应该使用 utf8mb4_bin

四、总结

  虽然推荐用 utf8mb4_unicode_ci,但是用 utf8mb4_general_ci 也没啥问题。因为 utf8mb4_unicode_ci 比较准确,utf8mb4_general_ci 速度比较快。通常情况下,新建数据库和创建 varchar 字符集类型字段时,一般选用 utf8mb4_general_ci 就可以。

  通过正确设置和使用字符集及排序规则,我们可以有效地在 MySQL 中存储和处理 Unicode 字符数据,确保数据的完整性和一致性。编码问题一直是web开发中的一个棘手问题,希望这篇文章能够帮助大家更好地理解和应对编码相关的挑战。

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19500.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

tcp 超时计时器

在 TCP(传输控制协议)中有以下四种重要的计时器: 重传计时器(Retransmission Timer) 作用:用于处理数据包丢失的情况。当发送方发送一个数据段后,就会启动重传计时器。如果在计时器超时之前没有…

Docker部署ES7.9.3单节点

Elasticsearch(简称ES)是一个分布式、可扩展、实时的搜索与数据分析引擎! Elasticsearch位于Elastic Stack核心,为所有类型的数据提供近乎实时的搜索和分析。无论是结构化或非结构化文本、数字数据还是地理空间数据,El…

ChromeDriver驱动下载地址更新(保持最新最全)

说明: ChromeDriver 是 Selenium WebDriver 用于控制 Chrome 的独立可执行文件。 为了方便下载使用,本文保持ChromeDriver的最新版本更新,并提供115.0.5763.0-133.0.6841.0版本的下载地址: 所有版本和下载地址: &am…

CSS:高级寄巧

精灵图 为什么需要精灵图呢? 一个网页中往往会应用很多小背景图作为修饰,当网页中的图像过多时,服务器就会频繁地接收和发送 请求图片,造成服务器请求压力过大,这将大大降低页面的加载速度。 因此,为了有…

AutosarMCAL开发——基于EB DsAdc驱动

目录 一、旋转变压器与DsAdc原理1.常见电机角度反馈方式2.可变磁阻旋变工作原理3.使用TC3XX EDSADC进行旋变软解码 二、EB配置1.载波输出2.通道配置3.调制器4.滤波链路5.整流6.积分 三、Mcal接口应用1.AUtosar标准API接口2.应用步骤 四、总结 一、旋转变压器与DsAdc原理 1.常见…

web应用安全和信息泄露预防

文章目录 1:spring actuator导致的信息泄露1.1、Endpoint配置启用检测1.2、信息泄露复现1.3、防御 2:服务端口的合理使用3:弱口令(密码)管理4:服务端攻击4.1、短信业务,文件上传等资源型接口1、…

C语言:链表

链表是一种常见的线性数据结构,其中每个元素(称为节点)包含两部分:数据和指向下一个节点的指针。链表的主要优点是插入和删除操作的时间复杂度较低,但随机访问的效率不如数组。 1. 链表的基本概念 节点(N…

webpack配置

4-3vue-loader测试_哔哩哔哩_bilibili 一.新建文件夹vue_todo,vscode打开 二.ctrl打开终端,输入npm init -y,快速生成一个默认的package.json文件 之后左边出现项目初始化文件package.json 三.接下来需要webpack完成打包,所以安装…

字节跳动辞退103人

大家好,我是程序员面试刷题平台的鸭鸭! 在前阵子实习生破坏大模型训练事件之后,字节又上了一次热搜。 鸭鸭吃完瓜,只能说,社会险恶啊同学们! 5 号,字节跳动内部发布了年内第四份《企业纪律与职…

大型语言模型综述 A Survey of Large Language Models

文章源自 2303.18223 (arxiv.org) 如有侵权,请通知下线 这是一篇关于大语言模型(LLMs)的综述论文,主要介绍了 LLMs 的发展历程、技术架构、训练方法、应用领域以及面临的挑战等方面,具体内容如下: 摘要…

服务器作业4

[rootlocalhost day04]# vim 10.sh [rootlocalhost day04]# cat 10.sh #通过shell脚本分析部署nginx网络服务 #1.接收用户部署的服务名称 read -p "服务名称:(nginx)" server if [ $server ! nginx ];then echo "输入的不是nginx,脚本退出" exit 1…

Linux基础(二十)——程序管理与 SELinux 初探

程序管理与 SELinux 初探 1. 程序和进程2.程序调用流程3. 一个bash中的多任务工作管理4.进程管理4.1 查询进程4.2 进程的执行顺序 5.系统资源的观察6. /proc/* 代表的意义7.SELinux 1. 程序和进程 2.程序调用流程 程序与进程之间的关系: 从上图可以看出&#xff0…

vue3 路由写法及传参方式 !超详细

Vue Router 是 Vue.js 官方的路由管理器。它主要用于单页面应用程序(SPA, Single Page Application)中,帮助解决页面导航、组件复用等问题。 基本的使用 1.router配置文件代码 创建一个ts文件,用来写路由器 // 创建一个路由器,并暴露出去 …

MATLAB绘制正四面体、正六面体

MATLAB绘制正四面体、正六面体 clc;close all;clear all;warning off;% clear all rand(seed, 100); randn(seed, 100); format long g;% 正四面体(Tetrahedron) % 顶点坐标(正四面体的顶点位于一个正方体的对角线上,并经过适当缩…

一文了解 inductive bias(归纳偏好)

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 归纳偏好(Inductive Bias)是机器学习中的一个非常基础但又非常重要的概念。为了更好地理解它,我们先从 “归纳” 和 “偏好” 这两个词开始讲解。 什么是归纳&#x…

leetcode844:比较含退格的字符串

题干 题目分析 两个字符串要进行比较,#代表着回车,也就是删除之前的字符。 若按照遍历的惯例,选择从前到后遍历,但这样没法判断,因为#之前被删除的部分是不需要相同的。 因此考虑到#的含义,我们应该选择从…

【Python爬虫实战】从入门到精通:全面解析IP代理池的原理与实战应用

🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、IP代理池 (一)基本概念 (二)主要功能 (三…

c++_day2

第一题: 继续为 mystring类编写以下方法: 1:析构函数,释放buf指向的堆空间 2:编写 append(const mystring r) 为当前字符串尾部,拼接新的字符串r 3:编写 isEqual(const mystring r) 判断当前字符串和 字符串…

机器学习基础06

目录 1.梯度下降 1.1梯度下降概念 1.2梯度下降公式 1.3学习率 1.4实现梯度下降 1.5API 1.5.1随机梯度下降SGD 1.5.2小批量梯度下降MBGD 1.6梯度下降优化 2.欠拟合过拟合 2.1欠拟合 2.2过拟合 2.3正则化 2.3.1L1正则项(曼哈顿距离) 2.3.2…