首页 > 数据库 >MySQL 5.7 和 8.0 几处细节上的差异【转】

MySQL 5.7 和 8.0 几处细节上的差异【转】

时间:2022-12-30 16:57:57浏览次数:44  
标签:8.0 hash 5.7 int t1 MySQL join

MySQL 8.0 相对于 MySQL 5.7,有很多新特性,比如:快速加列、原子 DDL、不可见索引、额外端口、角色管理等。这一节内容,就不讲这些新特性了,只来聊聊最近在工作学习过程中遇到的几处细节上的差异。

1 int 字段类型的差异

比如下面的建表语句,在 5.7 能正常执行:

CREATE TABLE `t1` ( `id` int(11) NOT NULL auto_increment,`a` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


但是在 8.0.17 开始后的版本,执行上面的建表语句,会有如下 warnings:


Integer display width is deprecated and will be removed in a future release.

 

在上面的建表语句中,int(11) 中的 11 表示最大显示宽度,从 MySQL 8.0.17 开始,int 类型就不推荐使用显示宽度这个属性了。因此 8.0 建议使用单独的 int 来定义整数数据类型,如下:

CREATE TABLE `t1` ( `id` int NOT NULL auto_increment,`a` int DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

 

2 创建用户和赋权差异

MySQL 5.7,可以直接使用 grant 命令,用户和赋权都能完成。


grant select on test.* to 'test_user'@'127.0.0.1' identified by 'ddafsduGdsag';

8.0 版本下不 create user 的情况下执行 grant 会报如下错误:


ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'ddafsduGdsag'' at line 1

 

因此 MySQL 8.0 如果需要创建用户并赋权,必须要先 create user,再执行 grant 命令,操作如下:

create user 'test_user'@'127.0.0.1' identified with mysql_native_password by 'ddafsduGdsag'; grant select on test.* to 'test_user'@'127.0.0.1';

 

3 Block Nested-Loop Join 算法

为了方便下面的实验,我们首先创建测试表并写入数据:

CREATE DATABASE test; /* 创建测试使用的database,名为test */use test; /* 使用test这个database */drop table if exists t1; /* 如果表t1存在则删除表t1 */CREATE TABLE `t1` ( /* 创建表t1 */`id` int(11) NOT NULL auto_increment,`a` int(11) DEFAULT NULL,`b` int(11) DEFAULT NULL,`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPCOMMENT '记录更新时间',PRIMARY KEY (`id`),KEY `idx_a` (`a`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
drop procedure if exists insert_t1; /* 如果存在存储过程insert_t1,则删除 */
delimiter ;;create procedure insert_t1() /* 创建存储过程insert_t1 */begindeclare i int; /* 声明变量i */set i=1; /* 设置i的初始值为1 */while(i<=10000)do /* 对满足i<=10000的值进行while循环 */insert into t1(a,b) values(i, i); /* 写入表t1中a、b两个字段,值都为i当前的值 */set i=i+1; /* 将i加1 */end while;end;;delimiter ; /* 创建批量写入10000条数据到表t1的存储过程insert_t1 */call insert_t1(); /* 运行存储过程insert_t1 */drop table if exists t2; /* 如果表t2存在则删除表t2 */create table t2 like t1; /* 创建表t2,表结构与t1一致 */insert into t2 select * from t1 limit 100; /* 将表t1的前100行数据导入到t2 */


对于下面这条 SQL(注意:两张表的 b 字段都没索引):

select * from t1 inner join t2 on t1.b = t2.b;


在 5.7 版本中的执行计划为:

图片

在 Extra 发现 Using join buffer (Block Nested Loop),这个就说明该关联查询使用的是 Block Nested Loop 算法(后面简称:BNL 算法)。BNL 算法的思想是:把驱动表的数据读入到 join_buffer 中,然后扫描被驱动表,把被驱动表每一行取出来跟 join_buffer 中的数据做循环对比,如果满足 join 条件,则返回结果给客户端。所以 BNL 是一个双重循环,时间复杂度为 O(n^2)如果 join_buffer 放不下的话,那将分成多个块,每个块再进行一次上面的操作。
在 8.0 版本中的执行计划如下:

图片

在 Extra 发现 Using join buffer (hash join),从 MySQL 8.0.20 开始,hash join 替换了 BNL。详情可参考官方文档:https://dev.mysql.com/doc/refman/8.0/en/hash-joins.html。hash join 算法的思想是:先把小一点的表采用 hash 函数,将连接键存放到内存的 hash table 中,然后扫描另外一张表,把另外一张表每一行取出来跟 hash table 中的数据做对比,如果满足 join 条件,则返回结果给客户端。与 BNL 算法相比,hash join 只有一次循环,时间复杂读为 O(n)。当表太大,无法一次性放入内存,就分成多个块,每个块再进行一次上面的操作。对于上面列子,我们可以使用下面的方式查看 hash join 的使用详情:


explain format=tree select * from t1 inner join t2 on t1.b = t2.b\G

图片

默认情况下,只要 MySQL 版本是 8.0.20 及以后的版本,hash join 默认开启的。

对于 hash join 和 BNL 的性能对比,可以参考:https://dev.mysql.com/blog-archive/hash-join-in-mysql-8/。

 

4 参考文档

    • Block Nested-Loop Join Algorithm:https://dev.mysql.com/doc/refman/8.0/en/nested-loop-joins.html

    • Hash Join Optimization:https://dev.mysql.com/doc/refman/8.0/en/hash-joins.html

    • Hash join in MySQL 8:https://dev.mysql.com/blog-archive/hash-join-in-mysql-8/

转自

MySQL 5.7 和 8.0 几处细节上的差异
https://mp.weixin.qq.com/s?__biz=MzIyOTUzNjgwNg==&mid=2247484592&idx=1&sn=19330707735b75d003e9ef6d2dfb9b85&chksm=e84061f9df37e8ef50bf4b7c47c36a662b7e115c6f0b9afe57c173a4cdb3f9d91ee9a3e202f2&scene=21#wechat_redirect

标签:8.0,hash,5.7,int,t1,MySQL,join
From: https://www.cnblogs.com/paul8339/p/17015265.html

相关文章

  • MySQL 5.7 并行复制实现原理与调优【转】
    MySQL5.7并行复制时代众所周知,MySQL的复制延迟是一直被诟病的问题之一,然而在Inside君之前的两篇博客中(1,2)中都已经提到了MySQL5.7版本已经支持“真正”的并行复制功能,官......
  • Mysql自动化安装脚本
    此脚本是Mysql安装脚本,有需要朋友可以参考,脚本内容如下:系统环境:CentOS7.4软件版本:5.7.29[root@localhost~]#vimauto_install_mysql.sh#!/bin/bash#2020-3-1210:31:01#B......
  • MYSQL最朴素的监控方式【转】
    对于当前数据库的监控方式有很多,分为数据库自带、商用、开源三大类,每一种都有各自的特色;而对于mysql数据库由于其有很高的社区活跃度,监控方式更是多种多样,不管哪种监控方......
  • Mysql权限整理及授权命令
    1、创建用户MariaDB[(none)]>usemysql;MariaDB[mysql]>createusertest@'%'identifiedby'123456';注意:test->新增的用户名,123456->用户密码,%表示任何IP都可访......
  • MySQL Binlog日志三种模式
    binlog 基本认识MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制......
  • mysql 修改密码
    1.使用mysqladmin修改密码使用mysqladmin命令修改MySQL的root用户密码格式为:mysqladmin-u用户名-p旧密码password新密码例如(root用户,root密码,修改密码为1234):......
  • MySQL高级
    大小写规范MySQL在Windows下是大小写不敏感的,会全部转换成小写MySQL在Linux下的大小写规则:数据库名、表名、表的别名、变量名是严格区分大小写的;关键字、函数......
  • MySQL 学习 --- 隔离级别
      文章图片来自参考文章,图片非原创概述事务隔离级别可解决的问题       下面的章节将会解释脏读,不可重复度和幻读。MySQL默认的事务隔离级别是可重复读(repeata......
  • MySQL 备份与恢复
    备份terminal窗口下mysqldump-h-p-u-pdb_name>路径名.sql-h主机名-p端口名-u用户名-p 用户密码db_name 数据库的名字例子#备份train数据库mysq......
  • mysql忘记root密码的解决办法
    mysql5.7mysql安装目录为/usr/local/mysql通过mysqld启动mysql服务。 /usr/local/mysql/bin/mysqld--skip-grant-tables--user=root [root@localhostbin]#/usr/local/......