mysql【周三】day10

课程回顾:
在这里插入图片描述

change buff 是辅助索引更新时,异步更新,不像是聚簇索引及时更新。

MRR : Multi Range Read
3.4.1 作用: 减少回表。减少随机IO。
3.4.2 开关方法:

mysql> set global optimizer_switch='mrr=on,mrr_cost_based=off';

如果没有mrr,从辅助索引会表到聚簇索引,进去取值,每次取到辅助索引就回表一次。
如果有mrr,从辅助索得到聚簇索引后,不会立即去回表查找数据,而是等到都取到了,一同去聚簇索引获取数据。
作用:减少IO,减少回表

没有MRR的情况
在这里插入图片描述
有了mrr之后的情况,如果id值临近,那么就可以通过双向指针,不再走根节点,减少性能消耗
在这里插入图片描述
mrr的启用(辅助索引):
mrr=no,
mrr_cost_based=on 如果后面的这个也是on的话,就是将主动权交给优化器,
如果是将mrr_cost_based=off 如果是off的话,那么就是我们主动强制开启mrr,不再交给优化器。

但是到底启用不启用mrr,要进行压测,一切以压测的速度为准,不能只看理论。
因为主要是看辅助索引得到的聚簇索引的ID数值是否是按照顺序来的,如果是回表时按照ID顺序,那么一定会加快查询,会使用双向指针,如果mrr取到的辅助索引回表时的值不是顺序的,那么开启mrr也不会得到明显的效果。

压力测试:

mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from world.city where name in ('Aachen','Aalborg','Aba','Abadan','Abaetetuba')" engine=innodb --number-of-queries=20000 -uroot -p123 -verbose

区别
具体参考 :

https://dev.mysql.com/doc/refman/5.7/en/mrr-optimization.html
https://mariadb.com/kb/en/multi-range-read-optimization/

多表联合查询的算法:

SNLJ 普通嵌套循环连接
例子:

A  join  B 
on   A.xx = B.yy 
where  

伪代码:

for each row in A matching range {
	block 
    for each row in B {
      A.xx = B.yy ,send to client
    }
}

例子:

mysql> desc select * from teacher join course on teacher.tno=course.tno;

优化器默认优化规则:

  1. 选择驱动表
    默认选择方式(非驱动表):
    选择非驱动表的方法:按照on的条件列,是否有索引,索引的类型选择。
  2. 在on条件中,优化器优先选择有索引的列为非驱动表。
  3. 如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。
    结果集小的做驱动表
for each row in course matching range {
    join buffer 
	block 
    for each row in teacher {
      course.tno = tracher.tno ,send to client
    }
 
}

desc的第一行就是驱动表,第二行就是非驱动表
关于驱动表选择的优化思路:
理论支撑:

mysql> desc   select * from city join country on city.countrycode=country.code ;
mysql> desc   select * from city left join country on city.countrycode=country.code ;

查询语句执行代价: 不光只看是否有主键与否,还和执行语句的代价有关

mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
mysql> desc   format=json select * from city left join country on city.countrycode=country.code ;

不管是什么理论合理,都需要进行压测之后再确定是否要强制指定非驱动表
实践检验:

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

注: 可以通过 left join 强制驱动表。

注: 可以通过 left join 强制驱动表。

BNLJ
作用:
在 A和B关联条件匹配时,不再一次一次进行循环。采用块循环连接。
A表中需要关联的数据,先在join buffer缓冲
而是采用一次性将驱动表的关联值和非驱动表匹配.一次性返回结果
主要优化了CPU消耗,减少了一部分IO消耗。

触发条件:非驱动表的连接条件有辅助索引。针对主键和唯一建是不生效的,因为如果是主键或者唯一建,走的是eq_ref了

In EXPLAIN output, 
use of BNL for a table is signified 
when the Extra value contains Using join buffer (Block Nested Loop)
For each tuple r in R do                             -- 扫描外表R
    store used columns as p from R in Join Buffer    -- 将部分或者全部R的记录保存到Join Buffer中,记为p
    For each tuple s in S do                         -- 扫描内表S
        If p and s satisfy the join condition        -- p与s满足join条件
            Then output the tuple                    -- 返回为结果集

BKA
主要作用,使用来优化非驱动表的关联列有辅助索引。
BNL+ MRR的功能。

开启方式:

mysql> set global optimizer_switch='mrr=on,mrr_cost_based=off';
mysql> set global optimizer_switch='batched_key_access=on';

重新登陆生效。

总结: 多表连接优化

  1. 驱动表选择
    A join B on A.x=b.y
    0.1. 让优化器自己决定:
    (1). 在on条件中,优化器优先选择有索引的列为非驱动表。
    (2). 如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。
    0.2. 自主选择:
    left join强制驱动表

0.3. 关于驱动表选择的优化思路:
理论支撑:

mysql> desc   select * from city join country on city.countrycode=country.code ;
mysql> desc   select * from city left join country on city.countrycode=country.code ;

查询语句执行代价:

mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
mysql> desc   format=json select * from city left join country on city.countrycode=country.code ;

实践检验:

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
1. 情景一: 触发SNL的情况

非驱动表,关联条件 如果没有任何索引的话,只能默认使用SNL算法
代价较高,建议做合理优化。
例如:将非驱动表关联条件建立索引。
(1)主键或唯一键,会自动使用eq_ref算法进行执行查询。
(2)辅助索引,默认会采用BNL。如果开启BKA,会走BKA。

  1. 情景二: 触发BNL的情况
    非驱动表,连接条件如果有普通索引。会默认会用BNL。

  2. 情景三: 触发BKA的情况
    非驱动表,连接条件如果有普通索引。
    默认是关闭的,启动方式:

mysql> set global optimizer_switch='mrr=on,mrr_cost_based=off';
mysql> set global optimizer_switch='batched_key_access=on';

选择 BNL和BKA算法的判断思路

理论支撑:

mysql> desc   select * from city join country on city.countrycode=country.code ;
mysql> desc   select * from city left join country on city.countrycode=country.code ;

查询语句执行代价:

mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
mysql> desc   format=json select * from city left join country on city.countrycode=country.code ;

实践检验:

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

最终结论:不管是优化单表或多表,重点是在于索引和语句本身优化。

MySQL 存储引擎

介绍
存储引擎MySQL中的“文件系统”

种类
Oracle MySQL自带的存储引擎种类

mysql> show engines;
MRG_MYISAM        
CSV               
MyISAM                      
BLACKHOLE         
PERFORMANCE_SCHEMA
InnoDB           ******       
ARCHIVE           
MEMORY            
FEDERATED     

彩蛋: 请你列举MySQL中支持的存储引擎种类?
InnoDB、MyISAM、CSV、MEMORY

分支产品的引擎种类介绍
TokuDB --》 percona、mariadb
MyRocks、Rocksdb
TokuDB引擎的特点
1. 压缩比15倍以上
2. 插入数据性能

适应场景: 例如Zabbix监控类的平台。

InnoDB存储引擎特性
MVCC : 多版本并发控制
聚簇索引 : 用来组织存储数据和优化查询
支持事务 : 数据安全保证
支持行级锁 : 控制并发 myisam是表级锁
外键
多缓冲区支持
自适应Hash索引: AHI
复制中支持高级特性。
备份恢复: 支持热备。
自动故障恢复:CR Crash Recovery
双写机制: Double Write

在这里插入图片描述

彩蛋: InnoDB 核心特性有哪些? InnoDB和MyISAM区别有哪些?
回答:
InnoDB 支持: 事务、MVCC、聚簇索引、外键、缓冲区、AHI、CR、DW,MyISAM不支持。
InnoDB 支持: 行级锁,MyISAM支持表级锁。
InnoDB 支持热备(业务正常运行,影响低),MyISAM支持温备份(锁表备份)。
InnoDB 支持CR(自动故障恢复),宕机自动故障恢复,保证数据安全和一致性可以得到保证。MyISAM不支持,宕机可能丢失当前修改。

案例1
1.1 环境: zabbix 3.2 + centos 7.3 + mariaDB 5.5 InnoDB引擎 ,zabbix系统 监控了2000多个节点服务
1.2 现象 : 每隔一段时间zabbix卡的要死 , 每隔3-4个月,都要重新搭建一遍zabbix,存储空间经常爆满.
1.3 问题 :
1.3.1. zabbix 版本过低。
1.3.2. 数据库版本
1.3.3 zabbix数据库500G,存在一个文件里ibdata1,手工删除1个月之前的数据,空间不释放。

1.4 优化建议:
1.4.1.数据库版本升级到percona 5.7+ 版本 mariadb 10.x+,zabbix升级更高版本
1.4.2.存储引擎改为tokudb
1.4.3.监控数据按月份进行切割(二次开发:zabbix 数据保留机制功能重写,数据库分表)
1.4.4.关闭binlog和双1
1.4.5.参数调整…
优化结果:
监控状态良好

为什么?
(1) 原生态支持TokuDB,另外经过测试环境,5.7要比5.5 版本性能 高 2-3倍
(2) TokuDB:insert数据比Innodb快的多,数据压缩比要Innodb高
(3)监控数据按月份进行切割,为了能够truncate每个分区表,立即释放空间
(4)关闭binlog ----->减少无关日志的记录.
(5)参数调整…----->安全性参数关闭,提高性能.

扩展:
部署 zabbix新版+ 新版本 tokudb VS 部署 zabbix + 低版本mariadb
Tokudb特性:

Additional features unique to TokuDB include:
Up to 25x Data Compression
Fast Inserts
Eliminates Slave Lag with Read Free Replication
Hot Schema Changes
Hot Index Creation - TokuDB tables support insertions, deletions and queries with no down time while indexes are being added to that table
Hot column addition, deletion, expansion, and rename - TokuDB tables support insertions, deletions and queries without down-time when an alter table adds, deletes, expands, or renames columns
On-line Backup

参考内容:

https://www.jianshu.com/p/898d2e4bd3a7
https://mariadb.com/kb/en/installing-tokudb/
https://www.percona.com/doc/percona-server/5.7/tokudb/tokudb_installation.html

案例2:
环境: centos 5.8 ,MySQL 5.0版本,MyISAM存储引擎,网站业务(LNMP),数据量50G左右
现象问题: 业务压力大的时候,非常卡;经历过宕机,会有部分数据丢失.

问题分析:
1.MyISAM存储引擎表级锁,在高并发时,会有很高锁等待
2.MyISAM存储引擎不支持事务,在断电时,会有可能丢失数据

职责
1.监控锁的情况:有很多的表锁等待
2.存储引擎查看:所有表默认是MyISAM

解决方案:

  1. 升级MySQL 5.6.1x版本
  2. 升级迁移所有表到新环境
  3. 开启双1安全参数

存储引擎的基本操作
查看存储引擎
查询支持的存储引擎

mysql> show engines;

查询、设置默认存储引擎

mysql> select @@default_storage_engine;
+--------------------------+
| @@default_storage_engine |
+--------------------------+
| InnoDB                   |
+--------------------------+
1 row in set (0.00 sec)
vim /etc/my.cnf  
default_storage_engine=InnoDB

重启生效。

查看、设定 表的存储引擎

1) 查看某张表的存储引擎

 mysql> show create table xta;

(2) 查询系统中所有业务表的存储引擎信息

 mysql> select 
 table_schema,
 table_name ,
 engine 
 from information_schema.tables  
 where table_schema not in ('sys','mysql','information_schema','performance_schema');

(3)创建表设定存储引擎

mysql> create table xxx (id int) engine=innodb charset=utf8mb4;

(4)修改已有表的存储引擎

  mysql> alter table xxx engine=myisam;
  mysql> alter table world.xxx engine=innodb;

(5)将所有的非InnoDB引擎的表查询出来,批量修改为InnoDB

 mysql> select table_schema,table_name ,engine 
  from information_schema.tables  
  where 
  table_schema not in ('sys','mysql','information_schema','performance_schema') 
  and engine !='innodb';
mysql> select concat("alter table ",table_schema,".",table_name," engine=innodb;")   from information_schema.tables     where    table_schema not in ('sys','mysql','information_schema','performance_schema')    and engine !='innodb' into outfile '/tmp/a.sql';
  mysql> source /tmp/a.sql

InnoDB 存储引擎的体系结构

InnoDB 存储引擎的体系结构

磁盘结构
表空间结构
介绍: 表空间的概念源于Oracle数据库。最初的目的是为了能够很好的做存储的扩容。
(1)共享(系统)表空间
ibdata1,5.5版本默认的表空间类型。
(2)ibdata1共享表空间在各个版本的变化
5.5版本:
系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、临时表信息、change buffer
用户数据: 表数据行、表的索引数据

5.6版本:共享表空间只存储于系统数据,把用户数据独立了。
系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、临时表信息、change buffer

5.7版本:在5.6基础上,把临时表独立出来,UNDO也可以设定为独立
系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、change buffer

8.0.19版本:在5.7的基础上将UNDO回滚信息默认独立
系统相关:Double Write信息、change buffer

8.0.20版本:在之前版本基础上,独立 Double Write信息
系统相关:change buffer

https://dev.mysql.com/doc/refman/5.7/en/innodb-architecture.html

(2)独立表空间
(3)undo表空间
(4)临时表空间

5.1.2 日志结构
5.1.3 其他结构

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章