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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql如何分析sql执行效率和进行效率优化

發(fā)布時間:2023/12/3 数据库 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql如何分析sql执行效率和进行效率优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【0】如何分析mysql中sql執(zhí)行較慢的問題

  • 步驟1、觀察,至少跑一天,看看生產(chǎn)的慢sql情況;
  • 步驟2、開啟慢查詢?nèi)罩?#xff0c;設(shè)置閾值,比如超過5秒鐘就是慢sql, 并將它抓取出來;
  • 步驟3、explain+慢sql分析;
  • 步驟4、show profile;(推薦)
  • 步驟5、運維經(jīng)理或dba,進行sql數(shù)據(jù)庫服務(wù)器的參數(shù)調(diào)優(yōu);(不推薦)

【總結(jié)】?

  • 總結(jié)1、慢查詢的開啟并捕獲;
  • 總結(jié)2、explain + 慢sql分析;
  • 總結(jié)3、show profile 查詢sql在mysql 服務(wù)器里面的執(zhí)行細節(jié)和聲明周期情況;
  • 總結(jié)4、sql數(shù)據(jù)庫服務(wù)器的參數(shù)調(diào)優(yōu);

==============================================================================================

【1】exists + order by + group by 優(yōu)化?

1.1、查詢優(yōu)化:使用 explain 查看執(zhí)行計劃,看是否可以基于索引查詢;

1.2、小表驅(qū)動大表:當兩個表做連接操作時, 其實就是雙層for循環(huán), 小表驅(qū)動大表的意思是, 小表(小數(shù)據(jù)集的表)放在第1層循環(huán),大表(大數(shù)據(jù)集的表)放在第2層循環(huán);

【補充】關(guān)于exists 語法 與 in 的區(qū)別:

exists語法:把 where id in 換位 where ?exists 即可;

select ... from tbl where exists (subquery);

exists語法可以理解為:將主查詢的數(shù)據(jù),放到子查詢中做條件驗證,根據(jù)驗證結(jié)果 true 或 false, 來決定主查詢的數(shù)據(jù)結(jié)果是否保留;
關(guān)于exists的提示:

  • 提示1:exists(subquery) 只返回true或false, 因此子查詢中的select * 也可以是 select 1 或其他, 官方說法是實際執(zhí)行時會忽略 select 清單,因此沒有區(qū)別;
  • 提示2:exists 子查詢的實際執(zhí)行過程可能經(jīng)過了優(yōu)化而不是我們理解上的逐條對比,如果擔心效率問題,可以進行實際檢驗;
  • 提示3:exists 子查詢往往也可以用條件表達式,其他子查詢或join來替代,哪種方法最優(yōu)需要具體問題具體分析;

exists用法荔枝(exists與in的區(qū)別):

-- exists 語法 select * from emp_tbl a where exists (select 1 from dept_tbl b where b.dept_id = a.dept_id) order by a.rcrd_id? limit 10 ; -- in 語法 select * from emp_tbl a where a.dept_id in (select b.dept_id from dept_tbl b) order by a.rcrd_id? limit 10 ;

-- 執(zhí)行計劃18 explain ?select * from emp_tbl a where exists (select 1 from dept_tbl b where b.dept_id = a.dept_id) ; -- 執(zhí)行計劃19 explain select * from emp_tbl a where a.dept_id in (select b.dept_id from dept_tbl b) ;

==============================================================================================

1.2、order by 關(guān)鍵字優(yōu)化?
優(yōu)化1、盡量使用index方式排序,避免使用 filesort方式;

-- 建表 drop table if exists birth_tbl; create table birth_tbl (`rcrd_id` int(10) unsigned primary key auto_increment COMMENT '記錄編號', age int default 0 comment '年齡', birth timestamp default current_timestamp comment '生日' ) engine=innodb default charset=utf8 comment '生日表' ; -- 插入數(shù)據(jù) insert into birth_tbl(age) values? (floor(1+(rand()*100))) , (floor(1+(rand()*100))) , (floor(1+(rand()*100))) , (floor(1+(rand()*100))) , (floor(1+(rand()*100))) ; -- 添加索引 alter table birth_tbl add key `idx_age_birth`(`age`, `birth`) ;?

-- 查看order by的執(zhí)行計劃是否使用了文件排序;?

-- 執(zhí)行計劃20 ?索引排序 explain select * from birth_tbl where age > 30 order by age ; -- 執(zhí)行計劃21 ?索引排序 explain select * from birth_tbl where age > 30 order by age, birth ; -- 執(zhí)行計劃22 ?文件排序 explain select * from birth_tbl where age > 30 order by birth ; -- 執(zhí)行計劃23 ?文件排序 explain select * from birth_tbl where age > 30 order by birth, age ; -- 執(zhí)行計劃24 ?文件排序 explain select * from birth_tbl order by birth ; -- 執(zhí)行計劃25 ?文件排序 explain select * from birth_tbl where birth > '2018-01-01 00:00:00' order by birth ; -- 執(zhí)行計劃26 ?索引排序 explain select * from birth_tbl where birth > '2018-01-01 00:00:00' order by age ; -- 執(zhí)行計劃27 ?文件排序 explain select * from birth_tbl order by age asc, birth desc ;

mysql支持兩種方式的排序: 文件排序filesort 和 index 索引排序, index排序的效率較高; 它指mysql 掃描索引本身完成排序,文件排序filesort 效率較低;

【補充】 order by 滿足兩個情況:會使用索引排序:

  • 情況1:order by 語句使用索引最左前列;
  • 情況2: 使用where子句與order by 子句條件組合滿足索引最左前列;

優(yōu)化2、盡可能在索引列上完成排序操作,遵照索引建的最佳左前綴;

優(yōu)化3、如果不在索引列上,文件排序filesort有兩種算法: mysql需要啟動雙路排序或單路排序;

優(yōu)化策略:

  • 策略1:增大 sort_buffer_size 參數(shù)設(shè)置;
  • 策略2:增大 max_length_for_sort_data 參數(shù)的設(shè)置;
  • 策略3:why ?

【總結(jié)】order by 總結(jié)-為排序使用索引:

  • 總結(jié)1、mysql兩種排序方式: 文件排序或掃描有序索引排序;
  • 總結(jié)2、mysql能為排序和查詢使用相同的索引;
  • 總結(jié)3、具體執(zhí)行計劃:

key idx_a_b_c(a, b, c);

  • 總結(jié)3.1、order by 能使用索引最左前綴的有:
  • order by a; order by a, b; order by a, b, c; order by a desc, b desc, c desc;? -- (要么全部升序,要么全部降序)
  • ?
  • 總結(jié)3.2、如果where 使用索引的最左前綴定義為常量, 則order by 能使用索引;
  • where a = const order by b, c; where a=const and b=const order by c; where a = const and b > const order by b, c;
  • ?
  • 總結(jié)3.3、不能使用索引進行排序:
  • order by a asc, b desc, c desc; where g = const order by b, c; where a = const order by c; where a=const order by a, d -- d不是索引的一部分; where a in (...) order by b, c;

1.3、group by 關(guān)鍵字優(yōu)化;(均和order by 一樣)

  • (1)group by 實質(zhì)是先排序后再分組,遵照索引建的最佳左前綴;
  • (2)當無法使用索引列,增大 max_length_for_sort_data 參數(shù)的設(shè)置+增大 sort_buffer_size 參數(shù)的設(shè)置;
  • (3)where高于 having, 能寫在 where 限定的條件就不要去 having 限定了 ;

=============================================================================================

【2】慢查詢?nèi)罩?/strong>

0、什么是慢查詢sql:sql運行時間超過 long_query_time 的sql 將會被記錄到 慢查詢?nèi)罩局?#xff1b;

  • 0.1)mysql的慢查詢?nèi)罩臼莔ysql提供的一種日志記錄, 它用來記錄在mysql中響應(yīng)時間超過閾值的語句,具體指運行時間超過 long_query_time 值的sql, 則會被記錄到慢查詢?nèi)罩局?#xff1b;
  • 0.2)long_query_time 的默認值為10, 則表示運行時間超過10秒的sql語句被記錄到慢查詢?nèi)罩局?#xff1b;
  • 0.3)通過收集超過10秒的sql, 結(jié)合之前 explain 進行全面分析;

1)mysql的慢查詢?nèi)罩?/strong>

  • 1.1)默認情況下, mysql沒有開啟慢查詢?nèi)罩?#xff0c;需要手工開啟;
  • 1.2)如果不是調(diào)優(yōu)需要的話,一般不建議啟動該參數(shù); 因為開啟慢查詢?nèi)罩净蚨嗷蛏贂硪欢ǖ男阅苡绊憽B樵內(nèi)罩局С謱⑷罩居涗泴懭胛募?#xff1b;

2)查看是否開啟慢查詢?nèi)罩疽约叭绾伍_啟??
默認: show variables like '%slow_query_log%';

開啟: set global slow_query_log=1;

【注意】

  • 注意1: 使用 set global slow_query_log=1 開啟了慢查詢?nèi)罩局粚Ξ斍皵?shù)據(jù)庫生效, 如果mysql重啟以后則會失效;
  • 注意2:如果要永久生效,必須修改配置文件 my.cnf ;

如何設(shè)置long_query_time ?
show variables like 'long_query_time%';
查詢 long_query_time的值?即查詢當前多少秒算慢?
show variables like 'long_query_time'

設(shè)置慢的閾值時間??
set global long_query_time=3;

為什么設(shè)置后期 long_query_time 還是沒變;
這個時候需要重新連接或新開一個會話; 或者執(zhí)行 show global variables like 'long_query_time' ;

如何制造 執(zhí)行時間超過3秒的SQL?
如 ?select sleep(4);

查看當前有多少條慢查詢sql?
show global status like '%slow_queries%';

補充1:如何在my.ini文件中配置mysql的慢查詢參數(shù), 如下:
補充2: 日志分析工具 mysqldumpslow ,常用于在生產(chǎn)中分析sql的性能;

?

=============================================================================================
【3】、批量數(shù)據(jù)腳本;

-- 新建函數(shù)-產(chǎn)生隨機的字符串 drop function if exists rand_str; delimiter ## create function rand_str(n int) returns varchar(255) begin declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';declare return_str varchar(255) default '';declare i int default 0;while i < n do set return_str=concat(return_str, substring(chars_str, floor(1+rand()*52), 1));set i=i+1;end while;return return_str; end ## delimiter ;-- 新建函數(shù)-產(chǎn)生隨機的整數(shù) drop function if exists rand_num; delimiter ## create function rand_num() returns int begin declare i int default 0;set i=floor(100+rand()*10);return i; end ## delimiter ;-- 創(chuàng)建存儲過程,函數(shù)沒法單獨被調(diào)用,只能通過存儲過程進行調(diào)用; -- 新建存儲過程-調(diào)用函數(shù)批量插入數(shù)據(jù) drop procedure if exists insert_emp; delimiter ## create procedure insert_emp(in start_num int, in max_num int) begin declare i int default 0;set autocommit=0;repeat set i=i+1;INSERT INTO mybatis.emp_tbl (emp_id, dept_id, name)VALUES(rand_num(), rand_num(), rand_str(20));until i = max_numend repeat;commit; end ## delimiter ;call insert_emp(0, 100000) ;

=============================================================================================

【4】show profile

4、show profile
4.0)intro:
show profile 提供了比 explain 更加細粒度的sql執(zhí)行計劃分析和sql優(yōu)化;
4.1)是什么: 是mysql提供可以用來分析當前回話中語句執(zhí)行的資源消耗情況。可以用于sql的調(diào)優(yōu)測量;
4.2)官網(wǎng): https://dev.mysql.com/doc/refman/8.0/en/show-profile.html?
4.3)默認情況下,參數(shù)處于關(guān)閉狀態(tài),并保持最近15次的運行結(jié)果;
4.4)分析步驟:

  • 步驟1:是否支持,看看當前的mysql版本是否支持 show profile;
  • show variables like 'profiling';
  • 步驟2:開啟功能,默認是關(guān)閉,使用前需要開啟;
  • 步驟3:運行 sql; 且要運行耗時長的sql;
  • select * from emp_tbl e inner join dept_tbl d on e.dept_id = d.dept_id ; select * from emp_tbl e left join dept_tbl d on e.dept_id = d.dept_id ; select * from emp_tbl group by rcrd_id%10? ;?
  • 步驟4:查看結(jié)果,show profiles;
  • 步驟5:診斷sql, show profile cpu, block io for query 上一步前面的問題sql數(shù)字號碼;?查看一條sql的完整生命周期;??show profile cpu, block io for query 3;?
  • 補充: 不僅僅可以查看 cpu, block io , 還可以查看如下類型的信息;
  • 步驟6: 日常開發(fā)需要注意的結(jié)論;以下結(jié)論都是性能比較差的sql的表現(xiàn)形式,即 show profile cpu, block io for query 3; 中的status中出現(xiàn)以下4種中的一種或幾種,則sql執(zhí)行效率較差,需要優(yōu)化;?

【關(guān)于show profile的結(jié)論】

  • 結(jié)論1)converting heap to myisam 查詢結(jié)果太大, 內(nèi)存都不夠用了,往磁盤上搬;
  • 結(jié)論2)creating tmp table 創(chuàng)建臨時表: 拷貝數(shù)據(jù)到臨時表,用完再刪除;
  • 結(jié)論3)copying to tmp table on disk, 把內(nèi)存中臨時表復制到磁盤,危險
  • 結(jié)論4) locked :鎖住;??
    ?

=============================================================================================

【5】、全局查詢?nèi)罩?#xff1b;
5.1、配置啟用: 在mysql的 my.ini 中,配置如下:

#開啟 general_log=1 #記錄日志文件的路徑 general_log_file=/path/logfile #輸出格式 log_output=FILE

5.2、編碼啟用:命令如下:

set global general_log=1; set global log_output='TABLE';


此后, 你所編寫的sql語句, 將會記錄到 mysql庫里的general_log 表,可以用下面的命令查看:
select * from mysql.general_log;?


5.3、建議不要在生產(chǎn)環(huán)境開啟這個功能, 僅在測試環(huán)境開啟以便調(diào)試;

?

【建議】 建議使用 show profile 功能分析和優(yōu)化sql性能;?
?

?

總結(jié)

以上是生活随笔為你收集整理的mysql如何分析sql执行效率和进行效率优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。