MySQL性能優化學習——(四)性能優化總結

一、優化思路

性能優化的思路應該是什麼樣的?

說到性能調優,大部分時候想要實現的目標是讓我們的查詢更快。
一個查詢的動作又是由很多個環節組成的,每個環節都會消耗時間,在第一篇 關於SQL 語句的
執行流程中已經分析過了。
想要減少查詢所消耗的時間,就要從每一個環節入手。
 
 

二、連接——配置優化

第一個環節是客戶端連接到服務端,連接這一塊有可能會出現什麼樣的性能問題?

 
有可能是服務端連接數不夠導致應用程序獲取不到連接。比如報了一個 Mysql: error
1040: Too many connections 的錯誤。
可以從兩個方面來解決連接數不夠的問題:
1、從服務端來說,我們可以增加服務端的可用連接數。
如果有很多請求同時訪問數據庫,連接數不夠的時候,我們可以:
(1)修改配置參數,增加可用連接數,修改max_connections的大小:
show variables like 'max_connections'; -- 修改最大連接數,當有多個應用連接的時候
 (2)或者即使釋放不活動的連接。交互式和非交互式的客戶端的默認超時時間都是28800秒,
8小時,我們可以把這個值調小。
show global variables like 'wait_timeout'; --及時釋放不活動的連接,注意不要釋放連接池還在使用的連接
 
2、從客戶端來說,可以減少從服務端獲取的連接數。
如果我們想要不是每次執行SQL都創建一個新的連接,應該怎麼做?
我們可以引入連接池,實現連接的重用。
 
我們可以在哪些層面使用連接池?
ORM層面:MyBatis自帶了一個連接池;
或者使用專業也連接池工具:阿里的Druid、Spring Boot 2.x版本默認的連接池Hikari、DBCP、C3P0;
 
當客戶端改成從連接池獲取連接之後,連接池的大小應該怎麼設置呢?
常有一個誤解,覺得連接池的最大連接數越大越好,這樣在高併發時客戶端可以獲取更多的連接數,不需要排隊。
這是錯誤的,連接池並不是越大越好,只要維護一定數量帶下的連接池,其他客戶端排隊等待連接就可以了。
有點時候連接池越大,效率反而越低。
 
Druid的默認最大連接池大小是8,Hikari的默認最大連接池大小是10,爲什麼默認值都這麼小?
在Hiari的github文檔中,給出了一個PostgreSQL數據庫建議的設置連接池大小的公式:

connections = ((core_count * 2) + effective_spindle_count)

它的建議是機器核數乘以 2 加 1。也就是說,4 核的機器,連接池維護 9 個連接就夠了。
這個公式從一定程度上來說對其他數據庫也是適用的。
 
爲什麼有的情況下,減少連接數反而會提升吞吐量呢?
爲什麼建議設置的連接池大小要跟 CPU 的核數相關呢?
每一個連接,服務端都需要創建一個線程去處理它。連接數越多,服務端創建的線程數就越多。
CPU的核數是有限的,執行多個線程,頻繁切換(線程)上下文會造成比較大的性能開銷。

 

不管是數據庫本身的配置,還是按照這個數據庫服務的操作系統的配置,

對配置進行優化,最終的目的都是使硬件本身的性能更好發揮,包括CPU、內存、磁盤、網絡。

在之前的內容中也接觸了很多的MySQL和InnoDB的配置參數,包括各種開關和數值的配置,

大多數參數都提供了一個默認值,比如默認的buffer_pool_size,默認的頁大小,InnoDB的併發線程數等等。

這些默認配置可以瞞住大部分情況的需求,除非有特殊的需求,在清楚參數的含義時再去修改它。

修改配置的工作一般由專業的DBA完成。

這是官網系統的參數列表,需要時再做參考:

https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html

 

除了合理設置服務端連接數和客戶端連接池大小外,還有哪些減少客戶端和數據庫服務端的連接數的方案呢?

可以引入緩存。

 

三、緩存——架構優化

3.1 緩存

在應用的併發數非常大的情況下,如果沒有緩存,會造成兩個問題:

一是會給數據庫帶來很大壓力,二是對於應用來說操作數據的速度也會受影響。

可以採用第三方緩存來解決這個問題,比如 Redis。

運行獨立的緩存服務,屬於架構層面的優化

爲了減少單臺數據庫服務器的讀寫壓力,在架構層面還可以做哪些其他優化措施?

還可以採取主從複製、分庫分表等方案。

 

四、優化器——SQL語句分析優化

優化器就是對我們的 SQL 語句進行分析,生成執行計劃。
 

4.1 慢查詢日誌(slow query log)

我們可以通過慢查詢日誌知道服務中哪些SQL語句比較慢。
 
因爲開啓慢查詢日誌是有代價的(和bin log、optimizer-trace一樣),所以默認關閉。
show variables like '%slow_query%';
 
除了這個開關,還有一個參數,控制執行多久的SQL才被記錄到慢日誌,默認是10秒:
show variables like '%long_query%';
可以直接動態修改參數(重啓後失效):
set @@global.slow_query_log=1; -- 慢查詢日誌開關  1 開啓,0 關閉,重啓後失效
set @@global.long_query_time=3; -- mysql 默認的慢查詢時間是 10 秒,另開一個窗口後纔會查到最新值
 
或者修改配置文件 my.cnf,讓配置永久生效。
以下配置定義了慢查詢日誌的開關、慢查詢的時間、慢日誌文件的存放路徑。
slow_query_log = ON
long_query_time=2
slow_query_log_file =/var/lib/mysql/localhost-slow.log
 
show global status like 'slow_queries'; -- 查看有多少慢查詢
show variables like '%slow_query%'; -- 獲取慢日誌目錄
 
雖然有了慢日誌,但是慢日誌記錄了所有超過設定值的慢查詢,如何統計分析呢?總不能一條一條數。
MySQL提供了mysqldumpslow的工具,在MySQL的bin目錄下。
例如:查詢用時最多的20條慢SQL:
mysqldumpslow -s t -t 20 -g 'select' /var/lib/mysql/localhost-slow.log
 
Count:代表這條SQL被執行了多少次;
Time:代表執行的時間,括號內是累計時間;
Lock:代表鎖定的時間,括號是累計鎖定時間;
Rows:代表返回的記錄數,括號是累計;
 
 

4.2 show profile

除了慢查詢日誌,還有show profile工具可以使用
https://dev.mysql.com/doc/refman/5.7/en/show-profile.html
 
 
show profile可以查看SQL語句執行的時使用的資源,比如CPU、IO的消耗情況。
 
查看是否開啓:
select @@profiling;
若未開啓則手動開啓:
set @@profiling=1;
 
查看 profile 統計
show profiles;(命令最後帶一個 s)
 
查看最後一個 SQL 的執行詳細信息,從中找出耗時較多的環節(沒有 s)。
show profile;
此處時間6.2E-5表示小數點左移 5 位,代表 0.000062 秒。
 
也可以根據 ID 查看執行詳細信息,在後面帶上 for query + ID。
show profile for query 1;
 
除了慢日誌和 show profile,如果要分析出當前數據庫中執行的慢的 SQL,還可以
通過查看運行線程狀態和服務器運行信息、存儲引擎信息來分析。
 

其他系統命令

show processlist 運行線程
show processlist;
用於顯示用戶運行線程。可以根據 id 號 kill 線程。
也可以查表,效果一樣:
select * from information_schema.processlist;
 
Id : 線程的唯一標誌,可以根據它 kill 線程
User : 啓動這個線程的用戶,普通用戶只能看到自己的線程
Host : 哪個 IP 端口發起的連接
db : 操作的數據庫
 
show status 服務器運行狀態
SHOW STATUS 用於查看 MySQL 服務器運行狀態(重啓後會清空),有 session 和 global 兩種作用域,格式:參數-值。
可以用 like 帶通配符過濾。
SHOW GLOBAL STATUS LIKE 'com_select'; -- 查看 select 次數
 
show engine 存儲引擎運行信息
show engine 用來顯示存儲引擎的當前運行信息,包括事務持有的表鎖、行鎖信息;
事務的鎖等待情況;線程信號量等待;文件 IO 請求;buffer pool 統計信息。
例如:
show engine innodb status;
 
如果需要將監控信息輸出到錯誤信息 error log 中(15 秒鐘一次),可以開啓輸出。
show variables like 'innodb_status_output%';
-- 開啓輸出:
SET GLOBAL innodb_status_output=ON;
SET GLOBAL innodb_status_output_locks=ON;
 
其實很多開源的慢查詢日誌監控工具,他們的原理其實也都是讀取的系統的變量和狀態。
 
那麼,現在我們已經知道哪些 SQL 慢了,爲什麼慢呢?慢在哪裏?
 
MySQL 提供了一個執行計劃的工具,
通過 EXPLAIN 我們可以模擬優化器執行 SQL 查詢語句的過程,來知道 MySQL 是
怎麼處理一條 SQL 語句的。通過這種方式我們可以分析語句或者表的性能瓶頸。
 

4.3 EXPLAIN 執行計劃

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