是什么影響了 MySQL 的性能?
松哥有兩個小伙伴最近在幫人改造一個系統,對方原本的系統是一個用 Java GUI 做的桌面應用,現在要用 Spring Boot 改造成一個 Web 應用。原本的應用在 Mac 上運行的時候非常絲滑,但是在 Windows 上運行的時候,就特別卡。經過分析之后,發現是因為數據庫中數據量過大導致每一次的查詢都非常緩慢。
為了解決這一問題,他們特地來咨詢了松哥,我也趁此機會整理了一下數據庫優化的基本操作,形成了幾篇文章,接下來就和小伙伴們逐一分享。
今天我們主要來看下,到底是什么影響了數據庫的性能?找到問題的原因,才能解決問題。
整體上來說,影響數據庫性能的因素,我們可以歸為以下幾個方面:
- SQL 腳本
- 數據庫服務器配置
- 網卡流量
- 磁盤 IO
- 大表操作
- 大事務操作
- 存儲引擎
- 數據庫參數配置
接下來我們就從這幾個方面來逐一進行說明。
1. SQL 腳本
SQL 腳本會影響到 MySQL 的執行效率,這個大家都懂,面試八股文中常見問題之一。其實也不是面試官故意愛考這個問題,只是這個東西太重要了,根據松哥的經驗,80% 的數據庫問題,都是由慢 SQL 導致的,都可以通過 SQL 優化來解決,所以 SQL 優化技能對于開發者而言就非常重要了(有條件的公司也可以聘請 DBA,但是大部分公司是沒有 DBA 的),這也是為什么我們在面試時經常會遇到 SQL 優化的原因。
那么慢 SQL 究竟會帶來哪些風險呢?
超高的 QPS 和 TPS
可能有人還不清楚什么是 QPS 和 TPS,因此我們這里先對這兩個做一個簡單介紹。
- TPS:英文全稱是 Transactions Per Second,即服務器每秒處理的事務數。TPS 包括一條消息入和一條消息出,加上一次用戶數據庫訪問。這里涉及到一個概念,就是事務。一個事務是指一個客戶機向服務器發送請求然后服務器做出反應的過程。客戶機在發送請求時開始計時,收到服務器響應后結束計時,以此來計算使用的時間和完成的事務個數。
- QPS:英文全稱是 Queries Per Second,即每秒查詢率。QPS 是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。舉個例子:假設數據庫處理一條 SQL 需要 10ms,那么 1s 就可以處理 100 條 SQL,那么我們說它 QPS<=100;假設數據庫處理一條 SQL 需要 100ms,那么 1s 就可以處理 10 條 SQL,那么我們說它 QPS<=10。
我們常用 QPS 和 TPS 來衡量 SQL 的處理效率。
數據庫連接被占滿
這個好理解,數據庫的連接數必然是有限的,在 MySQL 中,我們可以通過 max_connections 來設置數據庫的連接數(這個值默認是 100,生產環境下這個值可以適當調大)。慢 SQL 由于處理時間較長,因此占用數據庫連接的時間也較長,在高并發環境下這樣就容易導致數據庫連接被占滿。
超高的 CPU 使用率
慢 SQL 還會導致超高的 CPU 使用率,超高的 CPU 使用率會導致 CPU 資源耗盡進而出現宕機。
慢 SQL 真的危害很大!
2.數據庫服務器配置
這個應該好理解,不需要我多說吧。
服務器的硬件如 CPU、內存、磁盤 IO 等都會影響到 MySQL 性能,操作系統也會影響到 MySQL 性能。
3.網卡流量
網卡流量當然也會影響數據庫。網卡 IO 被占滿了一樣也是沒法操作數據庫,那么如何避免這一情況呢?
- 減少從服務器的數量,因為從服務器需要從主服務器同步數據,會占用網卡 IO(當然是在合理的范圍內減少從服務器的數量)。
- 數據分級緩存,避免突然的緩存失效對數據庫形成沖擊。
- 避免 select *,不僅浪費時間,還浪費網絡流量。
- 分離業務網絡和服務器網絡。
4.磁盤 IO
磁盤 IO 對數據庫性能的影響也是顯而易見的,因為數據庫無論怎么管理數據,最終都是要存入到硬盤中的,所以磁盤 IO 對數據庫的影響也就非常重要了。但是這個問題的解決,就只能使用更好更快的磁盤設備,例如 SSD。
另外,我們日常可能都會有一些定時的磁盤維護計劃,在一些高并發場景下(如促銷、618,雙11等),我們就需要調整磁盤維護計劃,避免在這些時候進行磁盤維護。同時一些大量消耗磁盤 IO 的工作如備份也需要在這個時候調整一下,例如原本在主庫上做的數據備份工作,在大促期間可以放到從庫上面做。
5.大表操作
大表操作也會影響到數據庫性能,那么什么樣的表就算大表呢?
大表沒有統一的標準,還是要結合具體的業務場景來定。
我舉一個比較常規的例子:
- 數據表中的行數超過千萬行。
- 數據表文件超過 10G。
當然,上面這個定義并不是絕對的,如果是一個操作日志表,日志表一般只會涉及到插入和簡單的查詢,基本上不會有 delete 和 update,那么對于這種表,即使超過了千萬行,也并不會影響我們的業務。但是如果是訂單表等業務表,超過千萬行就要小心了。
大表究竟會帶來哪些問題呢?
- 慢查詢:畢竟數據量大了,想要過濾出自己想要的數據,肯定費時間。從上千萬上億條數據中找出自己想要的數據,也會產生大量的磁盤 IO。
- DDL 操作恐怖:在大表上進行表定義操作也是一件非常恐怖的事情,例如建立索引、添加/刪除 字段,想想都可怕。在 MySQL5.5(不含) 之前,建立索引是會鎖表的,從 MySQL5.5(含) 開始,建立索引雖然不會鎖表,但是會引起主從延遲(因為要在主庫上操作完成之后,再將操作日志傳到從庫,然后完成同步)。
這就是大表所帶來的問題,一般來說,我們有兩種常見的解決思路:
- 分庫分表
- 歷史數據歸檔
至于什么時候用分庫分表,什么時候用歷史數據歸檔,這個松哥在以后的文章中再和大家介紹。
6.大事務操作
一些運行時間比較長,涉及到數據比較多的事務,我們可以稱之為大事務。大事務會鎖定很多條數據進行處理,這樣就容易造成大量的阻塞和鎖超時,并且一旦出錯發生回滾,回滾所需要的時間也會比較長,而且在回滾期間數據依然處于被鎖的狀態。
同時,由于大事務耗時較長,需要等到主庫事務執行完畢后,將操作日志寫入 binlog,然后從庫讀取 binlog 進行同步,這樣勢必會導致主從延遲。
解決大事務,兩個思路:
- 避免一次性處理太多數據。
- 移除事務中不必要的 SELECT 操作。
具體的操作方式,我們將在以后的文章中介紹。
7.存儲引擎
使用 MySQL 我們可以選擇不同的存儲引擎,不同的存儲引擎特點不同,最終對數據庫的影響也不同。例如 MySQL 中常見的 MyISAM、InnoDB 等存儲引擎。
MyISAM 不支持事務,而且是表級鎖;InnoDB 是事務級存儲引擎,支持行級鎖,也支持事務的 ACID 特性。
那么是不是說 InnoDB 就一定比 MyISAM 好呢?也不一定!這個還是要看具體的使用場景。
8.數據庫參數配置
大家都知道數據庫有很多配置參數,我們在數據庫優化時可對其進行配置,例如前面所說的 max_connections。這些參數中,有的參數對數據庫的性能影響較大,有的則影響較小,這個我們在以后的文章中再和大家詳細討論。
好啦,今天主要和小伙伴們探討了在我們日常開發中,到底有哪些東西會影響數據庫的性能!至于具體的解決方案,松哥將在接下來的文章中和大家細聊。
雖然我們不是專業的 DBA,但是從小伙伴們的面試經歷來看,數據庫優化顯然也不能一竅不通。
本文轉載自微信公眾號「江南一點雨」,可以通過以下二維碼關注。轉載本文請聯系江南一點雨公眾號。