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 其他結構

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