MySQL是怎样运行的——MySQL进阶

这篇具有很好参考价值的文章主要介绍了MySQL是怎样运行的——MySQL进阶。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在系统学习《MySQL是怎样运行的》过程中,写下了这篇学习笔记,会持续更新。
如果有一定的MySQL基础,会基本增删改查语法,可以直接看这本书,如果纯纯0小白,建议先看《MySQL是怎样使用的》
原书链接

在学习过程中配合官方文档食用更佳
MySQL官方文档英文版
MySQL官方文档中文版

1 装作自己是个小白 —— 重新认识MySQL

日常使用 MySQL 的情景一般是这样的:

  • 启动 MySQL 服务器程序。
  • 启动 MySQL 客户端程序并连接到服务器程序。
  • 客户端程序中输入一些命令语句作为请求发送到服务器程序,服务器程序收到这些请求后,会根据请求的内容来操作具体的数据并向客户端返回操作结果。

MySQL的服务器客户端本质上就是一个实例,是计算机中的进程,每次打开一个新的进程,操作系统都会给这个进程分配一个唯一的新进程号和一个名称,这个名称是我们自己定义的,比如MySQL服务器进程的默认名称就是mysqld,MySQL客户端进程的默认名称就是mysql

安装MySQL

网上安装MySQL的教程一抓一大把,自行学习(踩坑),这里主要唠一些需要注意的地方:

  • 安装一个完整的MySQL需要把服务器和客户端都安装好,大部分安装包两者都包含,但Linux下的RPM包需要分别安装两者
  • MySQL可以安装在各种各样的操作系统上,不管装在哪,一定要记住安装目录,非常重要!!!!!
  • MySQL的安装目录下有一个很重要的bin目录,里面有很多后缀为.exe的可执行文件

如何执行.exe文件?
对于有可视化界面的操作系统来说,鼠标双击就可以执行这些.exe文件(比如最常用的Windows系统就可以双击exe文件来执行);
如果没有可视化界面,可以在命令行(小黑屋)中执行这些.exe文件(Windows系统用cmd打开,UNIX系统用shell打开)
如何用命令行执行.exe文件?
如果没有配置环境变量,每次都需要从相对/绝对路径执行.exe文件,就很麻烦。比如你想执行mysqld.exe:
要么打开MySQL安装目录下的bin目录,在路径中输cmd,才能正常执行mysqld;
要么直接打开cmd,然后切目录切切切,切到这个bin目录下,再正常执行mysqld;
这两种方法本质上是没区别的,只是切换到bin目录下的方法不一样而已,但都非常麻烦,必须找对路径才能执行这个mysqld.exe。
如果配置了环境变量,把bin目录的路径加入到环境变量PATH中,就省事多了,一劳永逸。环境变量PATH就是一系列路径的集合,各个路径之间会隔开,当你在任意目录下的命令行中输入mysqld命令时,系统就会从PATH的一系列路径中依次寻找有没有mysqld这个命令,如果有,就执行mysqld。是不是非常省事,不用每次都纠结路径了。配置环境变量也很简单

启动/关闭MySQL服务器程序

  • Windows系统
    要么mysqld命令启动
    要么把mysqld注册成服务,通过net start/stop MySQL命令启动/关闭

注册成服务的好处?
操作系统会自动管理它,如果一台计算机需要长时间运行MySQL,且计算机一启动MySQL就需要启动,就赶紧把它注册成服务吧!!!
如何把mysqld注册成服务?
假设你已经配置好环境变量了,执行mysqld --install [-manual][服务名]命令就可以把mysqld命令注册成服务了
[-manual] 参数可以省略,不写表示开机自动启动,写表示开机不自动启动
[服务名] 参数也可以省略,不写是默认的服务名——MySQL

  • UNIX系统
    mysqld 命令 运行一次启动一个服务器进程,但不常用,因为有更高级的命令
    mysqld_safe 命令 间接调用mysqld命令,还会自动启动监控进程,还会生成出错日志,更高级
    mysqld.server start/stop 命令 不知道高级在哪,可能是不光可以开启,还能关闭吧,它是一个链接文件,一般安装的时候会自动在bin目录下面创建这个链接文件,如果没有,自己手动创建一个就行
    mysqld_multi 命令 可以监控多个服务器

启动/关闭MySQL客户端程序

  • 关闭客户端很简单,直接执行quit / exit / \q 命令,然后出现Bye就说明关了
  • 开启客户端还是要看bin目录,bin有很多客户端的exe文件,最重要的是mysql.exe,它可以实现客户端和服务器交互,也就是发送请求,接收结果,用法:
    mysql -h主机名 -u用户名 -p密码
    比如mysql -hlocalhost -uroot -p123456就启动了一个MySQL客户端,并连接到了一个服务器,服务器是本机localhost,用户名是root,密码是123456。

注意事项:
-h表示域名/IP地址,如果服务器运行在本机,就可以省略这个参数,或者写成-hlocalhost / -h127.0.0.1
只有一个英文字母的参数前面加一个短横线就行,比如-h -u -p,如果大于一个英文字母前面需要加两个短横线,比如--host --user --password,但效果是一样的,所以-hlocalhost 等价于 --host=localhost,其它也一样
最好不要直接mysql -hlocalhost -uroot -p123456输入密码,这样是明文,不安全,先执行mysql -hlocalhost -uroot -p,会弹出来Enter password:,这个时候再输入密码,显示的就是加密的星号,更安全
此外,mysql命令的各个参数的顺序没有硬性规定

连接客户端和服务器

客户端和服务器启动成功后,下一步就要把它们两个连接
MySQL客户端和服务器其实就是两个进程,所以它们的连接本质上就是进程通信而已

问题就可以转化为:进程的通信方式?主要有三种

  • TCP/IP
    MySQL服务器在启动的时候可以向操作系统申请一个端口号(0~65535的整数),客户端可以通过IP地址+端口号的方式和服务器连接通信

服务器启动的时候会自动默认申请3306端口号,也可以用mysqld -P3307 命令自定义端口号。
同样,客户端在启动的时候会默认连接3306端口,也可以用mysql -hlocalhost -uroot -P3307 -p 命令 自定义端口号
(注意区分大小写,大写的P才是端口号,小写的p是密码!!!)

  • 命名管道和共享内存
    Windows系统可以用这种方法
    命名管道:在启动服务器的命令中加上--enable-named-pipe参数,然后在启动客户端程序的命令中加上--pipe或者--protocol=pipe参数
    共享内存:在启动服务器的命令中加上--shared-memory参数,然后在启动客户端程序的命令中加上--protocol=memory参数。但是这种方法前提条件是客户端和服务器在同一台主机中。
  • Unix域套接字文件
    我暂时不用unix系统,先不研究了
    MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库

服务器处理请求

客户端和服务器连接成功而且可以正常通信后,服务器就会处理一堆堆客户端发来的请求
MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库
这三部分就是服务器处理客户端流程的大致过程

连接管理
这块涉及了很多知识,比如线程池、限流、认证、数据传输安全、文本消息…先说个大概,后续再展开

线程池:每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程来专门处理与这个客户端的交互。当该客户端退出时会与服务器断开连接,服务器并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来。另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端。这样就起到了不频繁创建和销毁线程的效果,从而节省开销。
限流:线程分配的太多会严重影响系统性能,所以也需要限制可以同时连接的客户端数量
认证:在客户端程序发起连接的时候,需要携带主机信息、用户名、密码,服务器程序会对客户端程序提供的这些信息进行认证,如果认证失败,服务器程序会拒绝连接。
数据传输安全:如果客户端程序和服务器程序不运行在一台计算机上,可以采用使用了 SSL (安全套接字)的网络连接进行通信,来保证数据传输的安全性
文本消息:MySQL 服务器接收到的请求只是一个文本消息,该文本消息还要经过各种处理才能被服务器利用起来进行下一步真正的处理

解析与优化
这块也涉及到了很多知识,比如查询缓存、语法解析、查询优化…同样先说个大概,后续再展开

查询缓存:MySQL 服务器程序处理查询请求的过程也是这样,会把刚刚处理过的查询请求和结果 缓存起来,如果下一次有一模一样的请求过来,直接从缓存中查找结果就好了,就不用再傻呵呵的去底层的表中查找了。这个查询缓存可以在不同客户端之间共享,也就是说如果客户端A刚刚查询了一个语句,而客户端B之后发送了同样的查询请求,那么客户端B的这次查询就可以直接使用查询缓存中的数据。
缓存远没有这么简单,会有各种各样的问题,比如缓存大量不命中如何处理?数据不一致怎么办?缓存失效怎么办?维护缓存造成的开销如何平衡?
因此,从MySQL 5.7.20开始,不推荐使用查询缓存,MySQL 8.0已经删除了缓存
语法解析:假如没有命中缓存,就要真正去数据库中查询数据了。但客户端发来的请求只是一段文本,所以服务器会先分析文本,判断语法对错,然后再提取要查询的表和条件啥的,放到服务器内部,就像编译一样,这个过程封装的很彻底,基本不会亲手编写的
查询优化:执行效率不高的时候,需要考虑优化来提升效率,比如建立索引、外连接改内连接、子查询改为连接啥的,优化完后会生成一个执行计划,可以用EXPLAIN语句查询这个计划,然后分析优化的效果

存储引擎

  • MySQL 服务器把数据的存储和提取操作都封装到了存储引擎里。我们知道 表 是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎负责的。

  • 索引index是在存储引擎层实现的,所以不同的引擎有不同的索引结构。引擎是基于表结构的,所以不同的表可以用不同的存储引擎

  • 在建表时可以用 engine = 引擎名 来指定引擎

  • 可以用SHOW ENGINES 命令 查看当前服务器支持哪些存储引擎

  • 可以用CREATE TABLE table_name(建表语句;) ENGINE = 存储引擎名称;指定某个引擎

  • 可以使用ALTER TABLE table_name ENGINE = 存储引擎名称;来修改表的存储引擎

  • InnoDB引擎:对事务完整性有较高要求,要求数据一致性,更新删除操作较多时,选它!!!

  • MyISAM引擎:事务完整性数据一致性要求不高,更新删除操作较少时,选它!!!

  • MEMORY引擎:数据存储在内存中,速度很快,但持久化不太行,只能做临时表对安全性要求不高,对速度要求较高,数据量不大时,选它!!!

InnoDB

  • MySQL5.5版本之后的默认引擎
  • 默认B+索引
  • InnoDB的每张表都会对应一个ibd文件,存储该表的表结构、数据、索引
  • 一个ibd文件是一个表空间tablespace,一个表空间分多个段segment,一个段分多个区extent,一个区分多个页page,一个页分多个行row,一行中有多个字段
    MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库
  • DML增删改操作遵循ACID模型,支持事务,支持行级锁,支持外键约束

MyISAM:

  • MySQL早期版本的默认引擎
  • 默认B树索引
  • 每张表会生成三个文件
  • 不支持事务,不支持外键,不支持行锁,但支持表锁,访问速度快

2 MySQL的调控按钮 —— 启动选项和系统变量

命令行设置启动项

我们可以在命令行设置MySQL的一堆东西,比如连入的客户端数量、客户端和服务器通
信方式、表的默认存储引擎、查询缓存的大小等,称为设置项,这些设置项一般都有默认值。

启动选项是啥?在程序启动时指定的设置项和参数就是启动项

大多数程序提供了--help,可以查看该程序支持的全部启动选项以及它们的默认值。
例如, mysql --help 可以看 mysql 程序支持的启动选项, mysqld_safe --help
可以看 mysqld_safe 程序支持的启动选项, mysqld --verbose --help可以查看 mysqld 支持的启动选项

在启动服务器程序的命令行后边指定启动选项的通用格式是这样的:--启动选项1[=值1] --启动选项2[=值2] ... --启动选项n[=值n]

常见启动选项:

  • 指定客户端和服务器之间通过TCP/IP网络通信 -h服务器IP地址
  • 禁止通过TCP/IP网络通信 mysqld --skip-networking / mysqld --skip_networking skip-networking是一个整体,是选项名,短横线改成下划线也可以
  • 修改默认引擎 mysqld --default-storage-engine=MyISAM,注意等号周围不能有空格

在命令行中设置启动选项只对当次启动生效,也就是说如果下一次重启程序的时候我们还想保留这些启动选项的话,还得重复把这些选项写到启动命令行中,这样真的神烦唉!于是设计 MySQL 的大叔们提出一种配置文件/选项文件的概念,我们把需要设置的启动选项都写在这个配置文件中,每次启动服务器的时候都从这个文件里加载相应的启动选项。由于这个配置文件可以长久的保存在计算机的硬盘里,所以只需我们配置一次,以后就都不用显式的把启动选项都写在启动命令行中了,所以我们推荐使用配置文件的方式来设置启动选项。

配置文件设置启动项(推荐)

配置文件其实就是一个普通文件而已,Windows是后缀.ini文件,UNIX是后缀.cnf文件,如果安装目录下没有这个文件,手动创建一个,然后把配置内容复制进文件里即可

配置文件的具体内容可以看这个

配置文件中的启动选项被划分为若干个组,每个组有一个组名,用中括号[] 扩起来,就像这样:

[server]
(具体的启动选项...)

[mysqld] # 这里还可以改成 [mysqld-5.7],表示只有版本号为 5.7 的 mysqld 程序才能使用这个选项组中的选项
# 设置3306端口
port = 3306
# 设置mysql的安装路径
basedir = xxx
# 设置mysql数据库的数据的存放目录
datadir = xxx\data
# 允许最大连接数
max_connections = 200
# 允许连接失败的次数。
max_connect_errors = 10
# 服务端使用的字符集默认为utf8
character-set-server = utf8
# 创建新表时使用的默认存储引擎
default-storage-engine = INNODB

[mysqld_safe]
(具体的启动选项...)
......

需要注意,配置文件中不能用一个字母的参数名,参数名前面不用加 – 前缀,每行只能设置一个参数,而且 = 周围可以有空白字符。对比一下,命令行设置上面配置文件中的内容大概就是这样:
-P3306 --basedir=xxx --character_set_server=utf8

  • mysql.server的启动参数必须用配置文件设置
  • 如果同一个启动选项既出现在命令行中,又出现在配置文件中,那么以命令行为准
  • 如果同一个启动选项出现在多个配置文件中,那以最后一个配置文件中的为准
  • 在命令行上指定的绝大部分启动选项都可以放到配置文件中,但有一些选项是专门为命令行设计的,比如 defaults-extra-file 、 defaults-file 是指定配置文件路径的,必须在命令行中设置,具体哪些启动选线必须用命令行请自行食用官方文档

那么操作系统是如何找到配置文件的?有Windows系统和UNIX系统两种情况,我先择一探索,想看UNIX版本可以看《MySQL是怎样运行的》P21:
MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库

系统变量

每个系统变量都有一个默认值,我们可以用命令行或者配置文件在启动服务器时改变一些系统变量的值。大多数的系统变量的值也可以在程序运行过程中修改,而且无需停止并重新启动程序。

  • 查看系统变量SHOW VARIABLES [LIKE 匹配的模式] 命令,like是用来筛选的,避免系统变量太多刷屏,看眼花了都
    比如SHOW VARIABLES LIKE 'default%'命令就可以筛选所有 default 开头的系统变量值
    再比如SHOW VARIABLES LIKE 'default_storage_engine'命令就可以精准定位 default_storage_engine 这个系统变量的值
  • 设置系统变量可以在启动服务器的时候通过设置启动选项的方式设置,如何设置启动选项请倒回去看上两个小节。

一个短横线两个短横线下划线傻傻分不清?下面是常用场景

  • 只有一个英文字母的参数前面加一个短横线就行,比如-h -u -p,如果大于一个英文字母前面需要加两个短横线,比如--host / --skip-networking / --skip_networking
  • 不管前面是一个短横线还是两个短横线,后面跟着的都有一个完整的参数名。
    如果参数是启动项,项名有好几个单词,各个单词之间用短横线 - 或者下划线 _ 连接起来都可以,比如mysqld --skip-networking / mysqld --skip_networking 都行。
    如果参数是系统变量,变量名有好几个单词,必须用下划线 _,比如SHOW VARIABLES LIKE 'default_storage_engine',这里的’default_storage_engine’就必须用下划线连接
    so,为了省事,其实可以全部统一用下划线_来分割过长的参数名

常见系统变量,更多的系统变量自行食用官方文档

  • 允许同时连入的客户端数量 max_connections
  • 表的默认存储引擎 default_storage_engine
  • 查询缓存的大小 query_cache_size

看到这儿肯定会疑惑一个问题,启动项和系统变量的区别?
大部分系统变量值可以在服务器运行过程中动态修改,不用重启服务器就能生效,启动项不行,启动项启动项,这个名字就注定了它只能在启动的时候修改

系统变量的作用范围

  • GLOBAL :全局变量,影响服务器的整体操作。
  • SESSION :会话变量,影响某个客户端连接的操作。(别名 LOCAL )

其实和Java中局部变量和全局变量的概念很像

在服务器启动时,会将每个全局变量初始化为其默认值(可以改默认值)。然后服务器还为每个连接的客户端维护一组会话变量,客户端的会话变量在连接时初始化为全局变量的值

如何设置系统变量的作用范围?

SET [GLOBAL|SESSION] 系统变量名 = 值;
SET [@@(GLOBAL|SESSION).]var_name = XXX;

比如,想让之后新连接到服务器的客户端都用 MyISAM 作为默认的存储引擎,可以这么写
SET GLOBAL default_storage_engine = MyISAM;
SET @@GLOBAL.default_storage_engine = MyISAM;

再比如,想让本客户端用 MyISAM 作为默认的存储引擎,可以这么写
SET SESSION default_storage_engine = MyISAM;
SET @@SESSION.default_storage_engine = MyISAM;
SET default_storage_engine = MyISAM;  # 不写就是默认session

如何查看指定作用范围的系统变量?

SHOW [GLOBAL|SESSION] VARIABLES [LIKE 匹配的模式];

比如,查看带有 default 的系统会话变量值可以这么写
SHOW SESSION VARIABLES LIKE 'default%';

需要注意的是,并不是所有系统变量都具有 GLOBAL 和 SESSION 的作用范围。
有一些系统变量只具有 GLOBAL 作用范围,比方说 max_connections ,表示服务器程序支持同时最多有多少个客户端程序进行连接。
有一些系统变量只具有 SESSION 作用范围,比如 insert_id ,表示在对某个包含 AUTO_INCREMENT 列的表进行插入时,该列初始的值。

3 乱码的前世今生——字符集和比较规则

字符集是用来映射字符串和二进制的
字符集超多,常用的有ASCII和utf-8,utf-8收录了地球上所有字符,还在不断扩充

MySQL中有两个新的概念
utf8mb3 (在MySQL中就叫utf8):阉割过的 utf8 字符集,只使用1~3个字节表示字符。
utf8mb4 :正宗的 utf8 字符集,使用1~4个字节表示字符。

如何查看当前 MySQL 中支持的字符集?

SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];
#  CHARACTER SET 和 CHARSET 是同义词,用哪个都可以
# 返回结果是一个表格,其中 Default collation 列表示默认的比较规则,Maxlen列表示一个字符最多需要几个字节

如何查看 MySQL 中支持的比较规则?文章来源地址https://www.toymoban.com/news/detail-759276.html

SHOW COLLATION [LIKE 匹配的模式];

4 从一条记录说起—— InnoDB 记录结构

5 盛放记录的大盒子 —— InnoDB 数据页结构

6 快速查询的秘籍 —— B+ 树索引

索引优化

  • 关系数据库中的一种数据结构,牺牲空间换时间,它将数据提前按照一定的规则进行排序和组织(例如现实生活中的目录等),能够帮助快速定位数据,加快数据库表中数据的查找和访问速度,降低访问磁盘IO的频率
  • 优点:提高检索效率,用默认的升序时可以自动排序,降低排序成本
  • 缺点:创建和维护索引需要耗费时间,索引需要占物理空间,每次增删改索引都需要动态维护,会降低表增删改的效率
  • 适合:查询(where)较频繁、排序(order by)较频繁、分组(group by)较频繁的字段
  • 不适合:字段值的唯一性太差不适合单独做索引,增删频繁的字段不适合,不会出现在where中的字段不需要做索引
  • 尽量选择区分度较高的字段作为索引,尽量建立唯一索引,多用联合索引(覆盖索引概率更大,减少回表),少用单列索引。字段长度较长且为字符串类型的建立前缀索引
  • 性能分析指标:show global status like ‘Com_________’,可以查看数据库的查询次数和插入删除次数,如果查询较频繁就可以通过建立索引进行优化
  • 慢查询日志:记录了所有执行时间超过指定参数的所有SQL语句的日志,可以针对慢查询日志中效率较低的SQL语句进行优化
  • profile详情:能告诉我们时间都耗费到哪里了,针对性进行优化
  • explain执行计划:用explain命令可以知道MySQL执行查询语句的具体信息,包括如何连接表,连接顺序等,比较常用
  • 创建索引:create index 索引名 on 表名(字段名)
  • 查看索引:show index from 表名
  • 删除索引:drop index 索引名 on 表名

按数据结构分类

B+树索引(重点)

  • MySQL的默认存储结构
  • 从二叉树——平衡二叉树——红黑树——B树——B+树演化而来
  • 二叉树存在问题:当数据有序插入时,会出现极端情况,二叉树退化成链表,查找效率低下
  • 平衡二叉树存在问题:虽然可以自动降低树的高度,但严格的左旋右旋操作较费时
  • 红黑树存在问题:不是非常严格的平衡二叉树,兼顾了树的高度和左旋右旋效率,但高度依旧不够低
  • B树存在问题:数据冗余、范围查询效率低下
  • B+树:本质上是平衡多路查找树,树的高度更低,还优化了B树存在的问题
  • 关键优化点1:B树不只将所有数据存储在叶子节点,为了方便寻址,还存了一份在非叶子节点中,会造成数据冗余。而B+树将所有数据存储在叶子节点,非叶子节点并没有存储数据
  • 关键优化点2:B树的叶子节点是独立的,在一定程度上不利于范围查询,而B+树将叶子节点的多个数据用双向指针链接起来,方便范围查询。例如当需要查询图中的1-5数据时,对于B+树来说,只需要从根节点出发,找到1,再从1出发根据指针直接找到2-5即可,而B树则需要从根节点出发查询5次
    MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库
  • 如果一个表没有主键索引还会创建B+树吗?:会。InnoDB(MySQL中的一种存储引擎)会为每个表创建一个主键索引,如果没有会用一个隐藏的自动生成的主键来创建索引(即B+树结构)

Hash索引

  • InnoDB不支持显式地创建Hash索引,Memory才支持
  • 解决冲突用的链表
  • 不支持排序,用的比较少

按物理存储分类

聚集索引

  • 索引和数据存储在一起
  • InnoDB的存储方式
  • 必须有,而且只有一个
  • 默认主键索引是聚集索引
  • 如果不存在主键,使用第一个唯一索引作为聚集索引
  • 如果不存在主键,也没有合适的唯一索引,InnoDB自动生成一个rowid作为隐藏的聚集索引

非聚集索引

  • 索引和数据分开存储,索引和指针存储在一起,根据指针去找数据
  • MyISAM的存储方式
覆盖索引
  • 算是一种聚集索引,例如 select id from ‘user’ where age=35 ,会另外建立一个关于age的二级索引B+树,叶子节点是age和主键id,但需要查询的字段id就在二级索引的叶子节点中,因此不需要回表,即索引列(叶子节点一整列,包括age和id)已经覆盖了查询字段id,查询速度更快,在实际开发中应尽量使用覆盖索引,避免 select *
    MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库
前缀索引
  • 字段类型为字符串,长度超级长时,可以简历前缀索引
  • 只将字符串的一部分前缀建立索引
  • 前缀长度如何决定:根据索引的选择性来决定,即不重复的索引值和数据表的记录总数比值,选择性越高查询效率越高。最好的情况是选择性为1的唯一索引
  • 选择性如何计算:用聚合函数count
二级索引
  • 一种非聚集索引,例如 select * from ‘user’ where age=35 ,也会另外建立一个关于age的二级索引B+树,叶子节点是age和主键id,通过二级索引查询所有数据时,需要先查到age字段对应的主键id,再通过回表去主键索引查所有信息。这里的二级索引属于非聚集索引(age、id和其他信息分开存储),主键索引就是聚集索引(id和对应的所有数据放在一起)
  • 可以存在多个
索引下推ICP
  • MySQL5.6针对二级索引做的优化
  • 适用于MYISAM和INNODB
  • 解决二级索引进行范围查询时需要频繁回表的问题

按字段个数分类

单列索引

  • 只有一个字段,如下图的右边子图的叶子节点,只有年龄和id,年龄就是索引列,也叫单列索引
  • MySQL会自动根据索引列的值进行排序,数字和字典都可以
    MySQL是怎样运行的——MySQL进阶,# 数据库,mysql,数据库

联合索引/复合索引/组合索引

  • 索引列由多个字段组成,如上图的左边子图的叶子节点,索引列有id名字和年龄多个索引列,但排序是先按id排序,id相同时再以名字排序
  • 最左前缀原则:带头大哥字段不能死,中间兄弟字段不能断。针对联合索引写查询语句时,必须把第一个有序的字段带上,放在最左边,而且不能跳过中间字段,因为后面的字段实际上在整体上是无序的。如在上图左子图中查 rob,不能直接 where name=rob,必须写 where id=5,name=rob,必须带上第一个字段id
  • 减少开销:假设需要频繁查询 a b c三个字段,建三个单列索引就需要建三个B+树,而建一个联合索引只需要一个B+树,可以减少写操作的开销和磁盘的开销
  • 覆盖索引:联合索引的叶子节点上的数据更全,查询时直接拿到数据无需回表的概率更大,可以减少io操作

索引失效情况

  • 索引列进行了运算
  • 字符串类型不加引号
  • 模糊查询:头部模糊会失效,比如查以 工程 结尾的某个字段就会失效,like ’%工程‘
  • or后面的条件没有索引:where 条件1 or 条件2; 如果条件2没有建立索引,即使条件1有索引也会失效
  • Mysql评估:MySQL评估后发现用索引比不用还慢,就会选择不使用索引

7 好东西也得先学会怎么用 —— B+ 树索引的使用

8 数据的家 —— MySQL 的数据目录

9 存放页面的大池子 —— InnoDB 的表空间

10 条条大路通罗马 —— 单表访问方法

11 两个表的亲密接触 —— 连接的原理

12 谁最便宜就选谁 —— MySQL 基于成本的优化

插入数据

  • insert 语句
  • 优化情况:插入多条数据
  • 优化方案1:不要单条插入,最好批量插入。批量插入建议不要一次性插入1000条以上
  • 优化方案2:手动提交事务。自动提交事务会频繁开关事务,建议将多条批量插入语句手动放在一个事务中提交
  • 优化方案3:主键顺序插入。顺序插入性能高于乱序插入
  • 优化方案4:当数据量高达百万,insert批量插入性能很差,建议使用MySQL提供的 load 指令

主键优化

  • 数组组织方式:对于InnoDB引擎,表数据都是根据主键顺序组织存放的,组织起来的表叫索引组织表
  • 页分裂(其实就是B+树插入一个数据时,该插入的页位置不够,需要增加一页的操作):InnoDB引擎是以页为单位进行管理的,主键顺序插入时会依次放入页中,满了再插一个无序数据时数据会将应插入的位置的前面一页的数据从中间分裂,用两页存储,称为页分裂。主键乱序插入会导致频繁发生页分裂,效率低下
  • 页合并(其实就是B+树删除一个数据时,删后的页只剩50%(默认值)以下的数据,就会检测前后页有没有空位能放下这些数据,如果能就合并页)
  • 主键的设计原则1:满足业务需求的前提下,主键长度尽可能短。因为所有二级索引都会在叶节点中存储字段+主键,主键若太长会很浪费空间,降低效率
  • 主键的设计原则2:尽量选择顺序插入,降低页分裂现象
  • 主键的设计原则3:尽量不用UUID做主键,UUID是乱序生成的,不利于顺序插入,且一般都比较长
  • 主键的设计原则4:尽量避免修改主键,一改就会牵引所有的索引修改

排序优化

  • order by语句
  • 两种排序方法:Using filesort 和 Using index
  • Using filesort:不走索引,全表扫描后在排序缓冲区中进行排序,然后直接返回排序结果
  • Using index:走索引,扫描有序索引,无需额外排序,直接返回有序数据,效率更高
  • 将排序尽量优化成 index 排序方法
  • 数据量很大,无法避免要用 filesort 时,可以增大排序缓冲区大小,避免因容量不够去磁盘中排序
  • 根据排序字段建立索引,尽量使用覆盖索引
  • 多字段排序时也要遵循最左前缀法则,若一个升序一个降序,注意联合索引在创建时的规则即可(ASC/DESC)

13 兵马未动,粮草先行 —— InnoDB 统计数据是如何收集的

14 不好看就要多整容 —— MySQL 基于规则的优化(内含关于子查询优化二三事儿)

15 查询优化的百科全书 —— Explain 详解(上)

16 查询优化的百科全书 —— Explain 详解(下)

17 神兵利器 —— optimizer trace 的神器功效

18 调节磁盘和CPU的矛盾 —— InnoDB 的 Buffer Pool

19 从猫爷被杀说起 —— 事务简介

20 说过的话就⼀定要办到 —— redo 日志(上)

21 说过的话就⼀定要办到 —— redo 日志(下)

22 后悔了怎么办 —— undo 日志 (上)

23 后悔了怎么办 —— undo 日志 (下)

24 一条记录的多幅面孔 —— 事务的隔离级别与MVCC

25 工作面试老大难 —— 锁

到了这里,关于MySQL是怎样运行的——MySQL进阶的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据库】MySQL 高级(进阶) SQL 语句

    location表格创建 store_info表格创建 显示表格中一个或数个字段的所有数据记录 不显示重复的数据记录 按照条件进行查询 在已知的字段数据取值范围内取值 另外还有not in命令,用法一致,表示显示不在指定范围内的字段的值。 在两个字段数据值之间取值,包含两边字段的数据

    2024年02月09日
    浏览(137)
  • nodejs进阶(6)—连接MySQL数据库

    连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 然后建一张表user如下 接下来我们利用nodejs连接mysql数据库 但是实际每次创建连接都需要一定的开销,执行效率就会有影响。下面介绍一种连接池连mysql的方法:node-mysql node-mysql是目前

    2024年02月05日
    浏览(44)
  • MySQL数据库——MySQL优化服务器,提高MySQL的运行速度!

    MySQL是一种广泛使用的关系型数据库管理系统,优化MySQL服务器可以显著提高数据库的性能和运行速度。在下面的回答中,我将介绍一些常见的MySQL优化策略和技术,以帮助提高MySQL服务器的性能。 1、优化数据库设计: 正确设计数据库结构,使用适当的数据类型、索引和约束

    2024年02月07日
    浏览(69)
  • 【一文详解】知识分享:(MySQL关系型数据库知识进阶)

    Mysql体系结构: 连接层 位于最上层,是一些客户端和连接服务,主要完成一些类似于连接处理,授权认证及相关的安全方案。 服务器也会为安全接入的每个客户端验证它所具有的操作权限。 服务层 第二层,主要完成大多数的核心服务功能,如sql接口,并完成缓存的查询,sql的分析和优

    2024年02月02日
    浏览(77)
  • 【MySQL进阶之路丨第二篇】数据库的安装与配置

    下载地址:MySQL下载地址 进入网址后,点击 MySQL Community Server : 选择版本: 我们选择历史版本中的5.7.24版本 安装到D盘的MySQL文件夹中 解压后复制bin目录路径 在系统变量的Path中添加bin目录路径 接着在D:SoftwareMySQLmysql-5.7.24-winx64目录下新增加一个配置文件mysql.ini和一个data文

    2024年02月10日
    浏览(45)
  • MySQL数据库进阶第二篇(索引,SQL性能分析,使用规则)

    本篇博客深入详细地介绍了数据库索引的概念和重要性。内容包含:索引的概念和目标、索引的优点与缺点。此外,博客还深入解析了三种主要的索引结构:B-Tree、B+Tree和Hash,提供了详细的结构解析和优化方法,并通过插图进一步增强了理解。 博客的部分内容专注于对B-Tr

    2024年02月21日
    浏览(66)
  • 【MySQL数据库原理】在MySQL Workbench界面运行SQL代码——学生管理系统

    在 MySQL Workbench 8.0 中,你可以使用以下步骤新建内容并运行 MySQL 语言代码: 1、打开 MySQL Workbench 并连接到你的 MySQL 数据库服务器。 2、在左侧的导航栏中,展开你的连接以查看数据库。选择你要在其中运行 SQL 代码的数据库。 3、在顶部菜单栏中,点击 “Query”(查询)选项

    2024年02月03日
    浏览(58)
  • 32.商务安全邮箱|JSP+ Mysql设计与实现(可运行源码+数据库+lw)

    推荐阅读100套最新项目 最新ssm+java项目文档+视频演示+可运行源码分享 最新jsp+java项目文档+视频演示+可运行源码分享 最新Spring Boot项目文档+视频演示+可运行源码分享 2024年56套包含java,ssm,springboot的平台设计与实现项目系统开发资源(可运行源代码+设计文档) 目录 文末获

    2024年04月22日
    浏览(29)
  • 基于Springboot+MYSQL+Maven实现的宠物医院管理系统(源码+数据库+运行指导文档+项目运行指导视频)

    本项目是一套基于springboot框架实现的宠物医院管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值 j

    2024年02月05日
    浏览(52)
  • 基于java Swing 和 mysql实现的购物管理系统(源码+数据库+说明文档+运行指导视频)

    本项目是一套基于java Swing 和 mysql实现的购物管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、项目文档、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,确保可以运行! 技术栈:Jav

    2024年02月10日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包