MySQL通過show status查看、explain分析優(yōu)化數(shù)據(jù)庫性能
1.概述
在應(yīng)用系統(tǒng)開發(fā)過程中,由于初期數(shù)據(jù)量小,開發(fā)人員寫SQL語句時更重視功能上的實現(xiàn),但是當(dāng)應(yīng)用系統(tǒng)正式上線后,隨著生產(chǎn)數(shù)據(jù)量的急劇增長,很多SQL語句開始逐漸顯露出性能問題,對生產(chǎn)環(huán)境的影響也越來越大,此時這些有問題的SQL語句就成為整個系統(tǒng)性能的瓶頸,因此我們必須要對它們進(jìn)行優(yōu)化,該章節(jié)將詳細(xì)介紹在MySQL中優(yōu)化SQL語句的方法。
2.通過show status命令了解各種SQL的執(zhí)行頻率
MySQL客戶端連接成功后,通過show [session|global]status命令可以提供服務(wù)器狀態(tài)信息,也可以在操作系統(tǒng)上使用mysqladmin extended-status命令獲得這些消息。show [session|global] status可以根據(jù)需要加上參數(shù)“session”或者“global”來顯示session級(當(dāng)前連接)的統(tǒng)計結(jié)果和global級(自數(shù)據(jù)庫上次啟動至今)的統(tǒng)計結(jié)果。如果不寫,默認(rèn)使用參數(shù)是“session”。
下面的命令顯示了當(dāng)前session中所有統(tǒng)計參數(shù)的值:
-- 查看會話所有統(tǒng)計的值 SHOW STATUS LIKE 'Com_%'; Or SHOW SESSION STATUS LIKE 'Com_%';
下面的命令顯示了當(dāng)前global中所有統(tǒng)計參數(shù)的值:
-- 查看全局所有統(tǒng)計的值
SHOW GLOBAL STATUS LIKE 'Com_%';
Com_xxx表示每個xxx語句執(zhí)行的次數(shù),我們通常比較關(guān)心的是以下幾個統(tǒng)計參數(shù):
- Com_select:執(zhí)行SELECT操作的次數(shù),一次查詢只累加1。
- Com_insert:執(zhí)行INSERT操作的次數(shù),對于批量插入的INSERT操作,只累加一次。
- Com_update:執(zhí)行UPDATE操作的次數(shù)。
- Com_delete:執(zhí)行DELETE操作的次數(shù)。
上面這些參數(shù)對于所有存儲引擎的表操作都會進(jìn)行累計。下面這幾個參數(shù)只是針對InnoDB存儲引擎的,累加的算法也略有不同。
- Innodb_rows_read:SELECT查詢返回的行數(shù)。
- Innodb_rows_inserted:執(zhí)行INSERT操作插入的行數(shù)。
- Innodb_rows_updated:執(zhí)行UPDATE操作更新的行數(shù)。
- Innodb_rows_deleted:執(zhí)行DELETE操作刪除的行數(shù)。
通過以上幾個參數(shù),可以很容易地了解當(dāng)前數(shù)據(jù)庫的應(yīng)用系統(tǒng)是以插入更新為主還是以查詢操作為主,以及各種類型的SQL大致的執(zhí)行比例是多少。對于更新操作的計數(shù),是對執(zhí)行次數(shù)的計數(shù),不論提交還是回滾都會進(jìn)行累加。
對于事務(wù)型的應(yīng)用,通過Com_commit和Com_rollback可以了解事務(wù)提交和回滾的情況,對于回滾操作非常頻繁的數(shù)據(jù)庫,可能意味著應(yīng)用編寫存在問題。此外,以下幾個參數(shù)便于用戶了解數(shù)據(jù)庫的基本情況。
- Connections:試圖連接MySQL服務(wù)器的次數(shù)。
- Uptime:服務(wù)器工作時間。
- Slow_queries:慢查詢的次數(shù)。
3.定位執(zhí)行效率較低的SQL語句
可以通過以下兩種方式定位執(zhí)行效率較低的SQL語句。
- 通過慢查詢?nèi)罩径ㄎ荒切﹫?zhí)行效率較低的SQL語句,用--log-slow-queries[=file_name]選項啟動時,mysqld寫一個包含所有執(zhí)行時間超過long_query_time秒的SQL語句的日志文件。
- 慢查詢?nèi)罩驹诓樵兘Y(jié)束以后才紀(jì)錄,所以在應(yīng)用系統(tǒng)反映執(zhí)行效率出現(xiàn)問題的時候查詢慢查詢?nèi)罩静⒉荒芏ㄎ粏栴},可以使用show processlist命令查看當(dāng)前MySQL在進(jìn)行的線程,包括線程的狀態(tài)、是否鎖表等,可以實時地查看SQL的執(zhí)行情況,同時對一些鎖表操作進(jìn)行優(yōu)化。
4.通過EXPLAIN分析低效SQL的執(zhí)行計劃
通過定位執(zhí)行效率較低的SQL語句后,可以通過EXPLAIN或者DESC命令獲取MySQL如何執(zhí)行SELECT語句的信息,包括在SELECT語句執(zhí)行過程中表如何連接和連接的順序,比如想統(tǒng)計所有庫存階梯數(shù)量,需要關(guān)聯(lián)goods_stock表和goods_stock_price表,并且對goods_stock_price.Qty字段做求和(sum)操作,相應(yīng) SQL 的執(zhí)行計劃如下:
EXPLAIN SELECT SUM(sp.Qty) FROM goods_stock AS s LEFT JOIN goods_stock_price AS sp ON s.ID=sp.GoodsStockID;
如上圖所示每個列的簡單解釋如下:
- select_type:表示 SELECT 的類型,常見的取值有:
- SIMPLE(簡單表,即不使用表連接 或者子查詢)。
- PRIMARY(主查詢,即外層的查詢)、UNION(UNION 中的第二個或 者后面的查詢語句)、◎SUBQUERY(子查詢中的第一個SELECT)等。
- table:輸出結(jié)果集的表。
- type:表示表的連接類型,性能由好到差的連接類型為:
- system(表中僅有一行,即常量表)。
- const(單表中最多有一個匹配行,例如primary key或者unique index)。
- eq_ref(對于前面的每一行,在此表中只查詢一條記錄,簡單來說,就是多表連接中使用primary key或者unique index)。
- ref(與eq_ref類似,區(qū)別在于不是使用primary key或者unique index,而是使用普通的索引)。
- ref_or_null(與ref類似,區(qū)別在于條件中包含對NULL的查詢)。
- index_merge(索引合并優(yōu)化)。
- unique_subquery(in的后面是一個查詢主鍵字段的子查詢)。
- index_subquery(與unique_subquery類似,區(qū)別在于in的后面是查詢非唯一索引字段的子查詢)。
- range(單表中的范圍查詢)。
- index(對于前面的每一行,都通過查詢索引來得到數(shù)據(jù))。
- all(對于前面的每一行,都通過全表掃描來得到數(shù)據(jù))。
- possible_keys:表示查詢時,可能使用的索引。
- key:表示實際使用的索引。
- key_len:索引字段的長度。
- rows:掃描行的數(shù)量。
- filtered:返回結(jié)果的行占需要讀到的行(rows列的值)的百分比。
- Extra:執(zhí)行情況的說明和描述。
- Using index(此值表示mysql將使用覆蓋索引,以避免訪問表)。
- Using where(mysql 將在存儲引擎檢索行后再進(jìn)行過濾,許多where條件里涉及索引中的列,當(dāng)(并且如果)它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶where子句的查詢都會顯示“Using where”。有時“Using where”的出現(xiàn)就是一個暗示:查詢可受益于不同的索引)。
- Using temporary(mysql 對查詢結(jié)果排序時會使用臨時表)。
- Using filesort(mysql會對結(jié)果使用一個外部索引排序,而不是按索引次序從表里讀取行。mysql有兩種文件排序算法,這兩種排序方式都可以在內(nèi)存或者磁盤上完成,explain不會告訴你mysql將使用哪一種文件排序,也不會告訴你排序會在內(nèi)存里還是磁盤上完成)。
- Range checked for each record(index map: N) (沒有好用的索引,新的索引將在聯(lián)接的每一行上重新估算,N是顯示在possible_keys列中索引的位圖,并且是冗余的)。
5.確定問題并采取相應(yīng)的優(yōu)化措施
經(jīng)過以上定位步驟,我們基本就可以分析到問題出現(xiàn)的原因。此時我們可以根據(jù)情況采取相應(yīng)的改進(jìn)措施,進(jìn)行優(yōu)化提高語句執(zhí)行效率。
在上面的例子中,已經(jīng)可以確認(rèn)是goods_stock是走主鍵索引的,但是對goods_stock_price子表的進(jìn)行了全表掃描導(dǎo)致效率的不理想,那么應(yīng)該對goods_stock_price表的GoodsStockID字段創(chuàng)建索引,具體命令如下:
-- 創(chuàng)建索引 CREATE INDEX idx_stock_price_1 ON goods_stock_price (GoodsStockID); -- 附加刪除跟查詢索引語句 ALTER TABLE goods_stock_price DROP INDEX idx_stock_price_1; SHOW INDEX FROM goods_stock_price;
創(chuàng)建索引后,我們再看一下這條語句的執(zhí)行計劃,具體如下:
EXPLAIN SELECT SUM(sp.Qty) FROM goods_stock AS s LEFT JOIN goods_stock_price AS sp ON s.ID=sp.GoodsStockID;
可以發(fā)現(xiàn)建立索引后對goods_stock_price子表需要掃描的行數(shù)明顯減少(從 3 行減少到1行),可見索引的使用可以大大提高數(shù)據(jù)庫的訪問速度,尤其在表很龐大的時候這種優(yōu)勢更為明顯。
到此這篇關(guān)于MySQL通過show status查看、explain分析優(yōu)化數(shù)據(jù)庫性能的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL中的SHOW FULL PROCESSLIST命令實現(xiàn)
SHOW FULL PROCESSLIST命令是MySQL中一個非常有用的工具,可以幫助我們理解和監(jiān)控MySQL服務(wù)器的狀態(tài),本文主要介紹了MySQL中的SHOW FULL PROCESSLIST命令,感興趣的可以了解一下2023-11-11從MySQL 5.5遷移到Mariadb 10.1.14所遇到的問題
這篇文章主要介紹了從MySQL 5.5遷移到Mariadb 10.1.14所遇到的問題的相關(guān)資料,需要的朋友可以參考下2016-08-08Windows平臺配置5.7版本+MySQL數(shù)據(jù)庫服務(wù)
這篇文章主要介紹了Windows平臺配置5.7版本+MySQL數(shù)據(jù)庫服務(wù)的方法,包括初始化root用戶密碼password的過程以及兩個常見問題的解決方法,需要的朋友參考下吧2017-06-06MySQL約束之默認(rèn)約束default與零填充約束zerofill
這篇文章主要介紹了MySQL約束之默認(rèn)約束default與零填充約束zerofill,MySQL?默認(rèn)值約束用來指定某列的默認(rèn)值。更多相關(guān)資料需要的朋友可以參考一下2022-07-07mysql.help_topic生成序列的方法實現(xiàn)
本文探討了如何使用MySQL的help_topic表生成序列,并介紹了相應(yīng)的SQL查詢語句和實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下2023-10-10淺談MySQL安裝starting the server失敗的解決辦法
如果電腦是不是第一次安裝MySQL,一般會出現(xiàn)報錯情況,starting the server失敗,通常是因為上次安裝的該軟件未清除干凈,本文就詳細(xì)的介紹一下解決方法,感興趣的可以了解一下2021-09-09MySQL中on?duplicate?key?update的使用方法實例
在做數(shù)據(jù)統(tǒng)計的時候,我們經(jīng)常會用到mysql的on duplicate key update語法來自動更新數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于MySQL中on?duplicate?key?update的使用方法的相關(guān)資料,需要的朋友可以參考下2022-09-09