MySQL 性能优化一
優化方向
硬件和OS調優 、MySql調優 、架構優化。對架構的優化對mysql的性能優化收益最高。本文主要討論架構優化。
架構優化
在系統設計時首先需要充分考慮業務的實際情況,例如排行榜的相關業務可以考慮遷移到redis中去做, 地理位置相關的需求放到mongodb中去做,有搜索需求放到ElasticSearch中去做,大數據相關的放到HBase中去做, 對數據一致性和事物有要求的,優先選擇MySql。采用更適合業務場景的架構能最大程度地提 升系統的擴展性和可用性。
MySql調優流程
- ????????確認業務表結構設計是否合理,SQL 語句優化是否足 夠,該添加的索引是否都添加了,是否可以剔除多余的索引等等。
- ????????確定系統、硬件有哪些地方需要優化,系統瓶頸在哪里,哪些系統參數 需要調整優化,進程資源限制是否提到足夠高;在硬件方面是否需要更換為具有 更高 I/O 性能的存儲硬件,是否需要升級內存、CPU、網絡等。
查詢性能優化
????????線上環境發現數據庫卡頓,需要首先分析慢查詢log, 定位慢查詢的sql, 優化對應的sql。
-
什么是慢查詢??
????????????????顧名思義,就是查詢花費大量時間的日志,是指 mysql 記錄所 有執行超過 long_query_time 參數設定的時間閾值的 SQL 語句的日志。
????????該日志能 為 SQL 語句的優化帶來很好的幫助。
-
慢查詢日志
????????默認情況下,慢查詢日志是關閉的,要使用 慢查詢日志功能,首先要開啟慢查詢日志功能。
-
慢查詢基礎-優化數據訪問
????????????????查詢性能低下最基本的原因是訪問的數據太多。大部分性能低下的查詢都可 以通過減少訪問的數據量的方式進行優化。對于低效的查詢,
????????一般通過下面兩個 步驟來分析總是很有效:
????????????????確認應用程序是否在檢索大量超過需要的數據。這通常意味著訪問了太 多的行,但有時候也可能是訪問了太多的列。
????????????????確認 MySQL 服務器層是否在分析大量超過需要的數據行。
-
請求了不需要的數據
????????有些查詢會請求超過實際需要的數據,然后這些多余的數據會被應用程序丟 棄。這會給 MySQL 服務器帶來額外的負擔,并增加網絡開銷,
????????另外也會消耗應 用服務器的 CPU 和內存資源。
-
查詢不需要的記錄
一個常見的錯誤是常常會誤以為 MySQL 會只返回需要的數據,實際上 MySQL 卻是先返回全部結果集再進行計算。我們經常會看到一些了解其他數據庫系統的人會設計
????????出這類應用程序。這些開發者習慣使用這樣的技術,先使用 SELECT 語句查詢大量的結果,然后獲取前面的 N 行后關閉結果集(例如在新聞 網站中取出 100 條記錄,
????????但是只是在頁面上顯示前面 10 條)。他們認為 MySQL 會執行查詢,并只返回他們需要的 10 條數據,然后停止查詢。實際情況是 MySQL 會查詢出全部的結果集,
????????客戶端的應用程序會接收全部的結果集數據,然后拋棄 其中大部分數據。最簡單有效的解決方法就是在這樣的查詢后面加上 LIMIT。.
-
總是取出全部列
每次看到 SELECT*的時候都需要用懷疑的眼光審視,是不是真的需要返回全 部的列?很可能不是必需的。取出全部列,會讓優化器無法完成索引覆蓋掃描這 類優化,
????????還會為服務器帶來額外的 I/O、內存和 CPU 的消耗。因此,一些 DBA 是 嚴格禁止 SELECT *的寫法的,這樣做有時候還能避免某些列被修改帶來的問題。 什么時候應該允許
????????查詢返回超過需要的數據?如果這種有點浪費數據庫資 源的方式可以簡化開發,因為能提高相同代碼片段的復用性,如果清楚這樣做的 性能影響,那么這種做法也是值得
????????考慮的。如果應用程序使用了某種緩存機制, 或者有其他考慮,獲取超過需要的數據也可能有其好處,但不要忘記這樣做的代 價是什么。獲取并緩存所有的列的查詢,相比
????????多個獨立的只獲取部分列的查詢可 能就更有好處。
-
重復查詢相同的數據
????????不斷地重復執行相同的查詢,然后每次都返回完全相同的數據。比較好的方 案是,當初次查詢的時候將這個數據緩存起來,需要的時候從緩存中取出,這樣 性能顯然會更好。
-
是否在掃描額外的記錄
????????????在確定查詢只返回需要的數據以后,接下來應該看看查詢為了返回結果是否 掃描了過多的數據。對于 MySQL,最簡單的衡量查詢開銷的三個指標如下: 響應時間、
???????掃描的行數、返回的行
-
響應時間
????????響應時間是兩個部分之和:服務時間和排隊時間。 服務時間是指數據庫處理這個查詢真正花了多長時間。 排隊時間是指服務器因為等待某些資源而沒有真正執行查詢的時間
????????—-可能 是等 I/O 操作完成,也可能是等待行鎖,等等。當你看到?一個查詢的響應時間的時候,首先需要問問自己,這個響應時間是 否是一個合理的值。概括地說,了解這個
????????查詢需要哪些索引以及它的執行計劃是 什么,然后計算大概需要多少個順序和隨機 I/O,再用其乘以在具體硬件條件下一次 I/O 的消耗時間。最后把這些消耗都加起來,就可以
????????獲得一個大概參考值來判 斷當前響應時間是不是一個合理的值。
-
掃描的行數和返回的行數
????????分析查詢時,查看該查詢掃描的行數是非常有幫助的。這在一定程度上能夠 說明該查詢找到需要的數據的效率高不高。 理想情況下掃描的行數和返回的行數應該是相同的。
????????但實際情況中這種“美 事”并不多。例如在做一個關聯查詢時,服務器必須要掃描多行才能生成結果集 中的一行。掃描的行數對返回的行數的比率通常很小,一般在 1:1 和
????????10:1 之間, 不過有時候這個值也可能非常非常大。
-
掃描的行數和訪問類型
????????在評估查詢開銷的時候,需要考慮一下從表中找到某一行數據的成本。 MySQL 有好幾種訪問方式可以查找并返回一行結果。有些訪問方式可能需要掃描 很多行才能返回
????????一行結果,也有些訪問方式可能無須掃描就能返回結果。在 EXPLAIN 語句中的 type 列反應了訪問類型。訪問類型有很多種,從全表 掃描到索引掃描、范圍掃描、唯一索引
????????查詢、常數引用等。這里列的這些,速度 是從慢到快,掃描的行數也是從小到大。你不需要記住這些訪問類型,但需要明 白掃描表、掃描索引、范圍訪問和單值訪問的概念。
???????? 如果查詢沒有辦法找到合適的訪問類型,那么解決的最好辦法通常就是增加 一個合適的索引,為什么索引對于查詢優化如此重要了。索引讓 MySQL 以最高 效、掃描行數最少
????????的方式找到需要的記錄。 一般 MySQL 能夠使用如下三種方式應用 WHERE 條件,從好到壞依次為
????????在索引中使用 WHERE 條件來過濾不匹配的記錄。這是在存儲引擎層完成 的。使用索引覆蓋掃描(在 Extra 列中出現了 Using index)來返回記錄,直接 從索引中過濾不需要
????????的記?錄并返回命中的結果。這是在 MySQL 服務器層完成的, 但無須再回表查詢記錄。從數據表中返回數據,然后過濾不滿足條件的記錄(在 Extra 列中出現 Using Where)。這在 ????????MySQL 服務器層完成,MySQL 需要先從數據表讀出記錄然 后過濾。
好的索引可以讓查詢使用合適的訪問類型,盡可能地只掃描需要的數據行。 如果發現查詢需要掃描大量的數據但只返回少數的行,那么通常可以嘗試下 面的技巧去優化它:
????????????????????????使用索引覆蓋掃描,把所有需要用的列都放到索引中,這樣存儲引擎無 須回表獲取對應行就可以返回結果了。
????????????????????????改變庫表結構。例如使用單獨的匯總表。
????????????????????????重寫這個復雜的查詢,讓 MySQL 優化器能夠以更優化的方式執行這個 查詢。
????????????????????????重構查詢的方式
????????????????在優化有問題的查詢時,目標應該是找到一個更優的方法獲得實際需要的結 果。 而不一定總是需要從 MySQL 獲取一模一樣的結果集。有時候,可以將查 詢轉換一種
?????????寫法讓其返回一樣的結果,但是性能更好。一個復雜查詢還是多個簡單查詢。如果一個查詢的需求很復雜,Sql語句很長,考慮把查詢語句拆分,拆成多個查詢語句,在應用
? ? ? ? ?層匯總?數據, 這樣做的好處提高sql閱讀和維護。
-
分解關聯查詢
????????很多高性能的應用都會對關聯查詢進行分解。簡單地,可以對每一個表進行 一次單表查詢,然后將結果在應用程序中進行關聯。
? ? ? ? ? ? ? ? ? ? ? ? 1. 讓緩存的效率更高。許多應用程序可以方便地緩存單表查詢對應的結果對象。 將查詢分解后,執行單個查詢可以減少鎖的競爭。
? ? ? ? ? ? ? ? ? ? ? ? 2. 在應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能和可擴 展。查詢本身效率也可能會有所提升。
? ? ? ? ? ? ? ? ? ? ? ? 3. 可以減少冗余記錄的查詢。在應用層做關聯查詢,意味著對于某條記錄應用 只需要查詢一次,而在數據庫中做關聯查詢,則可能需要重復地訪問一部分數據。
???????????????????????????這樣的重構還可能會減少網絡和內存的消耗。
? ? ? ? ? ? ? ? ? ? ? ? 4. 更進一步,這樣做相當于在應用中實現了哈希關聯,而不是使用 MySQL 的 嵌套循環關聯。某些場景哈希關聯的效率要高很多。
????????在很多場景下,通過重構查詢將關聯放到應用程序中將會更加高效,這樣的 場景有很多,比如:當應用能夠方便地緩存單個查詢的結果的時候、當可以將數 據分布
?????????到不同的 MySQL 服務器上的時候、當能夠使用 IN()的方式代替關聯查詢 的時候、當查詢中使用同一個數據表的時候。
-
慢查詢配置
????????我們已經知道慢查詢日志可以幫助定位可能存在問題的 SQL 語句,從而進行 SQL 語句層面的優化。但是默認值為關閉的,需要我們手動開啟。
查看慢查詢是否開啟?show VARIABLES like 'slow_query_log';? ? 如果off 則是關閉 需要開啟。
????????慢查詢開啟:?set GLOBAL slow_query_log=1; 再次調用上個命令查看是否開啟成功。
????????show VARIABLES like '%long_query_time%';? 運行時間超過該值的所有 SQL 語句都記錄到慢查詢日志中。
????????set? long_query_time=0; 設置慢查詢閾值,這里設置0是測試值, 實際設置值需要調整。
對于沒有運行的 SQL 語句沒有使用索引,則 MySQL 數據庫也可以將這 條 SQL 語句記錄到慢查詢日志文件,控制參數是:
show VARIABLES like '%log_queries_not_using_indexes%';
set GLOBAL log_queries_not_using_indexes=1; 開啟
慢查詢日志輸出位置
show VARIABLES like 'log_output';
小結
????????????????????????slow_query_log 啟動停止慢查詢日志?
????????????????????????slow_query_log_file 指定慢查詢日志得存儲路徑及文件(默認和數據 文件放一起)?
????????????????????????long_query_time 指定記錄慢查詢日志 SQL 執行時間得伐值(單位: 秒,默認 10 秒)?
????????????????????????log_queries_not_using_indexes 是否記錄未使用索引的 SQL
????????????????????????log_output 日志存放的地方可以是[TABLE][FILE][FILE,TABLE]
-
慢查詢解讀分析
日志格式
tail -f /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log // 這文件時執行slow_query_log_file 取的文件名
????????????????# Time: 2021-12-05T05:27:02.408009Z? ?//?查詢執行時間
????????????????# User@Host: root[root] @ localhost [] Id: 14 //?用戶名 、用戶的 IP 信 息、線程 ID 號
????????????????# Query_time: 0.000329 Lock_time: 0.000171 Rows_sent: 0 Rows_examined: 0
????????// Query_time?執行花費的時長(ms )Lock_time?執行獲得鎖的時長?Rows_sentc?獲 得的結果行數?Rows_examined?掃描的數據行數
????????????????SET timestamp=1638682022;//這 SQL 執行的具體時間
????????????????select * from student where sid=1000;//具體sql語句
-
慢查詢分析
????????慢查詢的日志記錄非常多,要從里面找尋一條查詢慢的日志并不是很容易的 事情,一般來說都需要一些工具輔助才能快速定位到需要優化的 SQL 語句,
????????下面介紹慢查詢輔助工具 mysqldumpslow 常用的慢查詢日志分析工具,匯總除查詢條件外其他完全相同的 SQL,并將 分析結果按照參數中所指定的順序輸出。
? ? ? ? ? ? ? ? 主要參數如下
????????????????語法: sudo mysqldumpslow -s r -t 5 /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log (sudo是我在ubuntu執行的 其他linux 不需要sudo)
????????-s order (c,t,l,r,at,al,ar)
????????c:總次數
????????t:總時間
????????l:鎖的時間
????????r?:獲得的結果行數 at,al,ar :指 t,l,r 平均數 【例如:at = 總時間/總次數】
????????????????-s 對結果進行排序,怎么排,根據后面所帶的 (c,t,l,r,at,al,ar),缺省為 at
? ?????????????????-t NUM just show the top n queries:僅顯示前 n 條查詢
??????????????????-g PATTERN grep: only consider stmts that include this string:通過 grep 來 篩選語句。
????????????????????????執行結果
????????????????????????Reading mysql slow query log from /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log
????????????????????????Count: 2 Time=0.00s (0s) Lock=0.00s (0s) Rows=19.0 (38), root[root]@localhost
????????????????????????show tables
????????????????????????Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=12.0 (12), root[root]@localhost
????????????????????????desc slow_log
????????????????????????Count: 2 Time=0.00s (0s) Lock=0.00s (0s) Rows=5.0 (10), root[root]@localhost
????????????????????????show databases
????????????????????????Count: 6 Time=0.00s (0s) Lock=0.00s (0s) Rows=1.0 (6), root[root]@localhost
????????????????????????show variables like 'S'
???????????????????????Count: 5 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.8 (4), root[root]@localhost
???????????????????????show VARIABLES like 'S'
總結:
掌握了Mysql慢查詢的意義和如何分析慢查詢,為執行計劃學習做準備,下一文章將分析MySql執行計劃。
技術參考
C/C++Linux服務器開發/后臺架構師【零聲教育】-學習視頻教程-騰訊課堂
總結
以上是生活随笔為你收集整理的MySQL 性能优化一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html特殊符号拉丁文,拉丁文字符号大全
- 下一篇: SQLServer2008不允许保存更改