首页 > 数据库 >MYSQL 5.7 升级 8.0 后的 由于字符集导致的大问题 ?

MYSQL 5.7 升级 8.0 后的 由于字符集导致的大问题 ?

时间:2023-06-22 12:05:43浏览次数:45  
标签:8.0 SET utf8mb4 utf8 5.7 字符集 MYSQL NULL


MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_数据库

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。

MYSQL 8.0 已经很多年了,但是,但是,但是,还有很多公司和业务项目在MYSQL5.6 ,5.7上继续奋斗,这还不是一个重要的问题,重要的问题是早期在MYSQL 5.7 上的一些基础,并未进行改变后到了MYSQL 8 上的使用一段时间产生的问题。

这里在MYSQL5.6,MYSQL.5.7上大部分的表还都是 utf8 , default charset =utf8  而在这些数据库升级的情况下,表基本上是照搬到MYSQL 8.0上的,但是后续会产生一个问题。建立新的表。此次我们采用MYSQL 最新的版本之一,MYSQL 8.030 来进行相关的问题的分析和查找。

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_02

下面就是一个典型的例子,在创建一个MYSQL的表的情况下,如果开发部指定 default charset=utf8 则默认建立新表就是utf8mb4 ,而这样就会产生一个严重的问题。

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_03

一个数据库中的表的字符集不一致。然后就会产生一个问题,两个表的字符集不同,如果两个表之间的查询是不关联的,这到不会造成什么严重的问题,而如果这两个表产生了之间的关联性那么问题就出现了。

我们创造一个奇怪的数据库,以及表,这里的表的字符集在 utf8  和  utf8mb4 之间混合着。

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_04

在这样的情况下,会产生如下一些假设,下面是一些表的表结构,其中orders的表,是UTF8MB4 格式 排序是 utf8mb4_9000_ai_ci  ,而我们的payments表是utf8mb3 的格式。

CREATE TABLE `orders` (

  `ordernumber` varchar(200) CHARACTER SET utf8 NOT NULL,

  `orderDate` date NOT NULL,

  `requiredDate` date NOT NULL,

  `shippedDate` date DEFAULT NULL,

  `status` varchar(15) CHARACTER SET utf8 NOT NULL,

  `comments` text CHARACTER SET utf8,

  `customernumber` varchar(200) CHARACTER SET utf8 DEFAULT NULL,

  PRIMARY KEY (`ordernumber`),

  KEY `customerNumber` (`customernumber`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

 CREATE TABLE `payments` (

  `customerNumber` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,

  `checkNumber` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,

  `paymentDate` date NOT NULL,

  `amount` decimal(10,2) NOT NULL,

  PRIMARY KEY (`customerNumber`,`checkNumber`),

  KEY `idx_payment` (`paymentDate`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

1   使用 left join 的时候,两个表,谁在前谁在后,优化器是否能正确运行相关结果。

explain select *

from payments as p 

left join (select * from orders) as o on p.customerNumber = o.customerNumber 

where paymentdate > '2005-01-01';

explain select *

from orders as o 

left join (select * from payments) as p on p.customerNumber = o.customerNumber 

where paymentdate > '2005-01-01';

语句如上,第一个语句为 utf8 作为驱动表,可以明显看到因为两个表的字符集和collation的不同,导致无法走索引进行查询,这里也就是 payments  的主键与order 的主键无法进行正确的连接和比对,而数据库没有办法,走了另外的优化方式,通过HASH JOIN 的方式进行处理。 

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_05

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_06

那么我们如果反过来进行查询的话情况是不是有变化,有些文章中提到变换驱动表关系,可以在有些版本上可以解决由于字符集不同的问题,导致的索引失效的问题。

那么我们变换一下驱动表的位置,整体的查询计划进行了变化,相关的执行计划的效率稍有提高。

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_07

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_08

我们将语句实际执行,并查看profilings ,这里可以看到的是,我们将payments 放到上面的情况下 executing  为 700 而将ORDER 放到驱动表的情况下,execute 变为 1742 

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_数据库_09

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_10

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_数据库_11

因为怕测试中的一些查询与表的行数等特征影响,我们在变化一下两个表的coding .

mysql> ALTER TABLE orders CONVERT TO CHARACTER SET utf8;

Query OK, 0 rows affected, 1 warning (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 1

mysql> 

mysql> 

mysql> ALTER TABLE payments CONVERT TO CHARACTER SET utf8mb4;

Query OK, 0 rows affected (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 0

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_ci_12

这里我们再次做相关的测试,发现调整后,

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_13

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_14

我看可以看到,实际上经过以上的操作和分析,如果作为驱动表,表小并且是utf8mb4的情况下,要比驱动表大并且是 utf8 的情况略好。

但如何,都不如统一的字符集让数据库的查询更能良好的运行。在我们统一字符到 utf8mb4 后,整体的查询正常了

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_数据库_15

所以以上列子中,主要是说明在MYSQL 5.7 迁移过来的表大部分都是 UTF8MB3 ,而如果MYSQL 8 不做任何处理,则新建的表是 UTF8MB4 ,所以,希望MYSQL 的同学注意以上问题,注意这样的情况,尽量避免。

另外还有一些事情,需要深入,有的时候即使字符集不同,collation的排序在某些情况下,在字符集不同的情况下还可以走索引。

MYSQL  5.7 升级 8.0 后的  由于字符集导致的大问题 ?_mysql_16

标签:8.0,SET,utf8mb4,utf8,5.7,字符集,MYSQL,NULL
From: https://blog.51cto.com/u_14150796/6534551

相关文章

  • POSTGRESQL 和 MYSQL 到底应该不应该控制活跃连接
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql ,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。最近群里某个同学的提问,引起的本篇文章,关于数据库连接的部分,没有废话,我们先针对MYSQL来说说数据库连接的部分。首先MYSQL的客......
  • 我也不知道该怎么回答这个问题,还学MYSQL 吗?
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题最近一个同学偶然问了我一个这样的问题,实话说我不知道该怎么回答这个问题。但我知道问这个问题的同学,他思考了,不是在追风,一会儿MYSQ......
  • MYSQL collation 选好还能换吗
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。Collation 主要的作用是什么,排序。 数据库中的字符众多,而在这里很多的查询中都对这些符号进行一些比对的工作,如A=a,B>B......
  • MySQL
    初识MySQLJavaEE:企业级Java开发、Web前端(页面:展示——数据);后端(连接点:连接数据库JDBC,连接前端——控制视图跳转和给前端传递数据);数据库(存数据,Txt,Excel,world)。程序员等级:只会写代码,没学好数据库,基本混饭吃。操作系统,数据结构预算法!当一个不错的程序员!离散数学、数字电路......
  • MySQL 视图&存储过程&函数
    1视图1.1视图的作用当我们创建一张表的视图后,可以用和表差不多的使用方式来使用视图,比如可以对视图进行select查询操作、过滤或者排序数据等等。同时,也可以联结其它视图或者表,甚至可以添加和更新数据(但一般不会这么做,而且存在诸多限制)。总结起来,视图有以下优点:重用SQL语句,简......
  • LoadRunner通过SiteScope监控MySQL的性能
    步骤:安装SiteScope下载Java版的MySQL驱动,下载地址:http://www.mysql.com/downloads/connector/j/下载成功后,把解压缩的mysql-connector-java-5.1.14-bin.jar文件放入:C:\SiteScope\java\lib\ext 以及 C:\SiteScope\java64\lib\ext目录下。重启系统.进入SiteSc......
  • MySQL约束
    1约束1.1约束分类NOTNULL:非空,用于保证该字段的值不能为空。比如姓名、学号等。DEFAULT:默认,用于保证该字段有默认值,比如性别。PRIMARYKEY:主键,用于保证该字段的值具有唯一性,并且非空。比如学号、员工编号等。UNIQUE:唯一,用于保证该字段的值具有唯一性,可以为空。比如座位号。......
  • mysql - #1067 - Invalid default value
    mysql中无法设置默认值为函数或者表达式,如果你强制设置时,就会报错误:#1067-Invaliddefaultvalue。这不是mysql的bug,而是故意这么设计的。参看:http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html这里写道:"TheDEFAULTvalueclauseinadatatypespecification......
  • 备份 mysql数据
    Mysql数据库的常用备份方法是使用使用mysqldump,其命令格式如下:#mysqldump[options]database[tables]其中参数的含义为:options:代表mysqldump的选项,通过mysqldump–help可以查到。database:代表将要备份的数据库tables:代表将要备份的表,如果不指定任何表,则备份整个数据库......
  • 基于 Flink CDC 构建 MySQL 到 Databend 的 实时数据同步
    这篇教程将展示如何基于FlinkCDC快速构建MySQL到Databend的实时数据同步。本教程的演示都将在FlinkSQLCLI中进行,只涉及SQL,无需一行Java/Scala代码,也无需安装IDE。假设我们有电子商务业务,商品的数据存储在MySQL,我们需要实时把它同步到Databend中。接下来的内......