日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Mysql调优你不知道这几点,就太可惜了

發布時間:2023/12/3 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mysql调优你不知道这几点,就太可惜了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??Mysql調優你不知道這幾點,就太可惜了

一、Mysql的邏輯分層

Mysql分為:連接層、服務層、引擎層、存儲層。

當客戶端向服務端發起操作請求的時候,執行過程是這樣的:

1、客戶端端與Mysql服務端的連接層建立連接,根據請求類型去選擇相應的服務層的請求接口。

二、SQL優化

1、Insert的優化

在執行insert操作時經常遇到插入多條數據的時候,例如:

  • 管理員在同時添加多名用戶的時候

  • 在某種數據結構比較復雜的情況下添加數據

在1對n的表結構的情況下,經常會遇到這種插入多次子表的情況。那么程序開發人員在開發時候,首先想到的是利用for循環進行插入子表數據:

第一種情況(合并插入)

例如:我想插入三條,利用for循環在循環3次才能執行,那么就需要這樣執行:

insert into st(name,password) values('zhangsan','123456'); insert into st(name,password) values('lisi','123456'); insert into st(name,password) values('wangwu','123456');

怎么才能改進呢?mysql的sql有一個語法可以支持,如下:

insert into st(name,password) values('zhangsan','123456'),('lisi','123456'),('wangwu','123456');

只有三條可能看不出來,那么接下來做一個測試,復制了50次遍。

  • 測試結果1:以單個插入的的方式,插入了50條數據,用了0.077s

測試結果2:插入了271條數據,用了0.077s

插入3241條用了0.044s


一個插入了50條數據,用了0.077s,一個插入了271條數據,用了0.077s。

很明顯的對比。

第二種情況(事務手動提交)

開啟事務,事務提交,改為手動提交。

start TRANSACTION; #先開啟事務insert into st(name,password) values('zhangsan','123456');insert into st(name,password) values('lisi','123456');insert into st(name,password) values('wangwu','123456'); COMMIT; #最后提交

?

測試結果:開啟事務后,插入50條數據用了0.040s,比沒開啟事務插入數據快了將近一半。

第三種情況(主鍵順序)

在插入大批量的數據時,建議歸類、有序的插入數據。

st(id key,name)

insert into st(name,id) values('zhangsana',10); insert into st(name,id) values('lisi',3); insert into st(name,id) values('wangwu',2); insert into st(name,id) values('wangwub',8); insert into st(name,id) values('wangwua',34);

優化后:(進行排序,按主鍵的順序)

insert into st(name,id) values(2,'wangwu'); insert into st(name,id) values(3,'lisi'); insert into st(name,id) values(8,'wangwub'); insert into st(name,id) values(10,'zhangsana'); insert into st(name,id) values(34,'wangwua');

?

2、order by的優化

環境準備

  • 準備測試表

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`age` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`sex` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  • 準備測試數據

INSERT INTO `user` VALUES ('1', 'zhangsan', 'zhangsan123', '30', '男', 'zhangsan@163.com'); INSERT INTO `user` VALUES ('2', 'lisi', 'lisi', '21', '男', 'lisi@163.com'); INSERT INTO `user` VALUES ('3', 'wangwu', 'wangwu', '34', '男', 'wangwu@163.com'); INSERT INTO `user` VALUES ('4', 'zhaoqi', 'zhaoqi', '32', '男', 'zhaoqi@163.com'); INSERT INTO `user` VALUES ('5', 'wuliu', 'wuliu', '33', '男', 'wuliu@163.com'); INSERT INTO `user` VALUES ('6', 'xiaoming', 'xiaoming', '51', '男', 'xiaoming@163.com'); INSERT INTO `user` VALUES ('7', 'xiaozhang', 'xiaozhang', '23', '男', 'xiaozhang@163.com'); INSERT INTO `user` VALUES ('8', 'xiaoli', 'xiaoli', '30', '男', 'xiaoli@163.com'); INSERT INTO `user` VALUES ('9', 'xiaozheng', 'xiaozheng', '13', '男', 'xiaozheng@163.com'); INSERT INTO `user` VALUES ('10', 'xiaohua', 'xiaohua', '54', '男', 'xiaohua@163.com'); INSERT INTO `user` VALUES ('11', 'xiaozeng', 'xiaozeng', '66', '男', 'xiaozeng@163.com'); INSERT INTO `user` VALUES ('12', 'xiaozhao', 'xiaozhao', '12', '男', 'xiaozhao@163.com'); INSERT INTO `user` VALUES ('13', 'xiaoa', 'xiaoa', '32', '男', 'xiaoa@163.com'); INSERT INTO `user` VALUES ('14', 'xiaob', 'xiaob', '13', '男', 'xiaob@163.com'); INSERT INTO `user` VALUES ('15', 'xiaoc', 'xiaoc', '32', '男', 'xiaoc@163.com'); INSERT INTO `user` VALUES ('16', 'xiaod', 'xiaod', '43', '男', 'xiaod@163.com'); INSERT INTO `user` VALUES ('17', 'xiaoe', 'xiaoe', '23', '男', 'xiaoe@163.com'); INSERT INTO `user` VALUES ('18', 'xiaof', 'xiaof', '65', '男', 'xiaof@163.com'); INSERT INTO `user` VALUES ('19', 'xiaog', 'xiaog', '30', '男', 'xiaog@163.com'); INSERT INTO `user` VALUES ('20', 'xiaoe', 'xiaoe', '30', '男', 'xiaoe@163.com');
  • 建立索引
#給id與age建立索引 create index index_user_salary_age on user(age,salary); #查詢表的索引 show index from testdb.user;

兩種排序方式

1)filesort排序

EXPLAIN select * from user ORDER BY age;

  • 多字段排序

  • 多字段升序或者降序,都是走的全表掃描

可以從上面的例子中看出,都是Using filesort,全部走了全表掃描

效率是比較低的。

2)index排序

通過using index排序???????

#在查詢的時候,只把加了索引的給查出來 EXPLAIN select id,age,salary from user ORDER BY age DESC,salary DESC;

  • 如果想要其他字段也想走index排序的話,也需要給這個字段加上索引

  • 給username加索引

  • 給username加索引后

3)多字段排序

  • 一個升序一個降序

EXPLAIN select id,age,salary,username from user ORDER BY age asc,salary DESC;

總結:最好不要既有升序也有降序,效率會降低。

  • 顛倒排序的位置

如果位置有變化了,也會影響效率。排序的位置,最好和索引的順序符合。

在優化排序的相關sql時,盡量減少額外的字段排序,通過索引直接返回有序的數據。where條件和Order by 使用相同的索引并且Order By的順序和索引順序相同,并且Order by 的字段都是升序或者都是降序。

Filesort優化

1)兩次掃描算法

在MySQL4.1之前,使用該方式排序。首先根據條件取出排序字段和行指針信息,然后在排序區sort buffer中排序,如果sort buffer不夠則在臨時表temporary table中存儲排序結果。完成排序之后,再根據行指針回表讀取記錄,該操作可能會導致大量隨機I/O操作。

2)一次掃描算法

一次性取出滿足條件的所有字段,然后在排序區sort buffer中排序后直接輸出結果集。排序時內存開銷較大,但是排序效率比兩次掃描算法高的多。

?

MySQL通過比較系統變量max_length_for_sort_data的大小和Qury語句取出的字段總大小,來判定是否符合哪種排序算法,如果max_length_for_sort_data更大,則使用第二種優化之后

?

三、JOIN的用法

直接用代碼表示的話,不能很直觀的看到效果,為了方便,我使用圖片+SQL的形式來講解。

在實際的數據庫應用中,我們經常需要從多個數據表中讀取數據,這時我們就可以使用SQL語句中的連接(JOIN),在兩個或多個數據表中查詢數據。

JOIN 按照功能可分為如下三類:

  • INNER JOIN(內連接,或等值連接):獲取兩個表中字段匹配關系的記錄;

  • LEFT JOIN(左連接):獲取左表中的所有記錄,即使在右表沒有對應匹配的記錄;

  • RIGHT JOIN(右連接):與 LEFT JOIN 相反,用于獲取右表中的所有記錄,即使左表沒有對應匹配的記錄。

有以下幾個表:

學生表(students):student_id,student_name,sno,class_id; 學號,姓名,學號,班級號

班級表(classes):student_id,class_name,class_id; 學號,姓名,班級

四、額外補充能量

  • 利用存儲過程大批量插入數據

    1、創建存儲過程

DELIMITER inData CREATE PROCEDURE insertData() BEGIN SET @i=1; WHILE @i<=10000 DO INSERT INTO st(name) VALUES(CONCAT("user",@i)); #拼接USER 和i值 SET @i=@i+1; #防止成為死循環 END WHILE; #結束循環 END inData #結束自定義結束符 DELIMITER ;

2、查詢存儲過程

show create PROCEDURE insertData ;\G

3、使用存儲過程

CALL insertData()

為什么要優化?

隨著數據量的增大, mysql服務性能差從而直接影響用戶體驗。

查詢時結果顯示的很慢等。

哪些方面可以優化?

1、優化硬件、操作系統

2、優化MySQL服務器

3、優化DB設計

4、優化SQL語句

5、優化應用

1、優化硬件、操作系統

-CPU,內存,硬盤

Linux操作系統的內核優化

內核相關參數(/etc/sysctl.conf)

-網絡TCP連接

-加快資源回收效率

-增加資源限制

-改變磁盤調度策略

?

2、優化MySQL服務器

最大連接數:

max_connections=2000

默認:max_connections=151

?

指定MySQL可能的連接數量

#指定MySQL可能的連接數量。當MySQL主線程在很短的時間內得到非常多的連接請求,該參數就起作用,之后主線程花些時間(盡管很短)檢查連接并且啟動一個新線程。

#back_log參數的值指出在MySQL暫時停止響應新請求之前的短時間內多少個請求可以被存在堆棧中。

back_log=1024

默認:back_log=80

?

索引塊的緩沖區大小

key_buffer_size = 32M

#索引塊的緩沖區大小,對MyISAM表性能影響最大的一個參數.決定索引處理的速度,尤其是索引讀的速度。默認值是8M,通過檢查狀態值Key_read_requests

#和Key_reads,可以知道key_buffer_size設置是否合理

默認:key_buffer_size=8M

?

MySQL執行排序使用的緩沖大小

sort_buffer_size = 16M

#是MySQL執行排序使用的緩沖大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。

#如果不能,可以嘗試增加sort_buffer_size變量的大小。

默認:sort_buffer_size=256K

?

MYSQL讀入緩沖區大小

read_buffer_size = 64M

#是MySQL讀入緩沖區大小。對表進行順序掃描的請求將分配一個讀入緩沖區,MySQL會為它分配一段內存緩沖區。read_buffer_size變量控制這一緩沖區的大小。

#如果對表的順序掃描請求非常頻繁,并且你認為頻繁掃描進行得太慢,可以通過增加該變量值以及內存緩沖區大小提高其性能。

默認:read_buffer_size=64K

Join操作緩存大小

join_buffer_size = 16M

#應用程序經常會出現一些兩表(或多表)Join的操作需求,MySQL在完成某些 Join 需求的時候(all/index join),為了減少參與Join的“被驅動表”的

#讀取次數以提高性能,需要使用到 Join Buffer 來協助完成 Join操作。當 Join Buffer 太小,MySQL 不會將該 Buffer 存入磁盤文件,

#而是先將Join Buffer中的結果集與需要 Join 的表進行 Join 操作,

#然后清空 Join Buffer 中的數據,繼續將剩余的結果集寫入此 Buffer 中,如此往復。這勢必會造成被驅動表需要被多次讀取,成倍增加 IO 訪問,降低效率。

默認:join_buffer_size=256K

MySQL的隨機讀緩沖區大小

read_rnd_buffer_size = 32M

#是MySQL的隨機讀緩沖區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀緩存區。進行排序查詢時,MySQL會首先掃描一遍該緩沖,以避免磁盤搜索,

#提高查詢速度,如果需要排序大量數據,可適當調高該值。但MySQL會為每個客戶連接發放該緩沖空間,所以應盡量適當設置該值,以避免內存開銷過大。

默認:read_rnd_buffer_size=256K

緩存排序索引大小

myisam_sort_buffer_size = 256M

#當對MyISAM表執行repair table或創建索引時,用以緩存排序索引;設置太小時可能會遇到” myisam_sort_buffer_size is too small”

myisam_sort_buffer_size=102M

緩存空閑的線程以便不被銷毀

thread_cache_size = 384

#thread_cahe_size線程池,線程緩存。用來緩存空閑的線程,以至于不被銷毀,如果線程緩存在的空閑線程,需要重新建立新連接,

#則會優先調用線程池中的緩存,很快就能響應連接請求。每建立一個連接,都需要一個線程與之匹配。

默認:thread_cache_size=10???????

set global max_connections=2000;#設置最大連接數 set global key_buffer_size=512*1024*1024;#設置索引塊緩沖區大小 set global sort_buffer_size=128*1024*1024;#MySQL執行排序使用的緩沖大小 set global read_buffer_size=64*1024*1024;#MYSQL讀入緩沖區大小 set global join_buffer_size=128*1024*1024;#Join操作緩存大小 set global read_rnd_buffer_size=32*1024*1024;#MySQL的隨機讀緩沖區大小 set global myisam_sort_buffer_size=256*1024*1024;#緩存排序索引大小 set global thread_cache_size=384;#緩存空閑的線程以便不被銷毀 set global innodb_buffer_pool_size=1000*1024*1024;#內存

#查詢SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size'

???????

3、優化DB設計

-參照范式進行設計(1級范式)

1NF

    包含分隔符類字符的字符串數據。

    名字尾端有數字的屬性。

    沒有定義鍵或鍵定義不好的表。

 2NF

    多個屬性有同樣的前綴。

    重復的數據組。

    匯總的數據,所引用的數據在一個完全不同的實體中。

    BCNF- “每個鍵必須唯一標識實體,每個非鍵熟悉必須描述實體。

 4NF

    三元關系(實體:實體:實體)。

    潛伏的多值屬性。(如多個手機號。)

    臨時數據或歷史值。(需要將歷史數據的主體提出,否則將存在大量冗余。)

?

-建立合適的索引

建索引的目的

加快查詢速度。
減少I/O操作,通過索引的路徑來檢索數據,不是在磁盤中隨機檢索。
消除磁盤排序,索引是排序的,走完索引就排序完成

1)B-Tree 索引

B-Tree 索引是 MySQL 數據庫中使用最為頻繁的索引類型

2)Hash 索引

Hash 索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree索引需要從根節點到枝節點,最后才能訪問到頁節點這樣多次的IO訪問,所以Hash索引的查詢效率要遠高于B-Tree索引。

3)什么時候可以建索引

1)列無重復值,可以建索引:唯一索引和普通索引

2)聚集索引和非聚集索引都可以是唯一的。因此,只要列中的數據是唯一的,就可以在同一個表上創建一個唯一的聚集索引和多個唯一的非聚集索引。

3)建了索引性能得到提高

4)區分度高的列可以建索引,比如表示男和女的列區分度就不高,就不能建索引

5)什么時候不可以建索引

1.頻繁更新的字段不適合建立索引

2.where條件中用不到的字段不適合建立索引

3.表數據可以確定比較少的不需要建索引

4.數據重復且發布比較均勻的的字段不適合建索引(唯一性太差的字段不適合建立索引),例如性別,真假值

5.參與列計算的列不適合建索引,如select * from where amount+1>10

6.查詢返回的記錄數不適合建立索引

7.查詢的排序表記錄小于40%不適合建立索引

8.查詢非排序表的記錄小于 7%不適合建立索引

9.表的碎片較多(頻繁增加、刪除)不適合建立索引

?

4、優化架構設計方案

  • 加緩存

  • DNS輪詢

通過在DNS-server上對一個域名設置多個ip解析,來擴充web-server性能及實施負載均衡的技術 。

  • LVS(負載均衡)

Linux Virtual Server,使用集群技術,實現在linux操作系統層面的一個高性能、高可用、負載均衡服務器 。

  • nginx:一個高性能的web-server和實施反向代理的軟件

一個高性能的web-server和實施反向代理的軟件

?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Mysql调优你不知道这几点,就太可惜了的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。