mysql 慢查询过多_MySQL 慢查询优化
為什么查詢速度會慢
1.慢是指一個查詢的響應時間長。一個查詢的過程:
- 客戶端發送一條查詢給服務器
- 服務器端先檢查查詢緩存,如果命中了緩存,則立可返回存儲在緩存中的結果。否則進入下一個階段
- 服務器端進行SQL解析、預處理,再由優化器生成對應的執行計劃。
- MySQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢。
- 將結果返回給客戶端
2.數據訪問
- 是否向數據庫請求了不需要的數據
- 是否掃描額外的記錄
3.查詢的方式
- 一個復雜的查詢還是多個簡單的查詢
- 切分查詢(將大查詢切分成小查詢,循環完成小查詢)
- 分解關聯查詢
慢查詢分析
問題SQL
把復雜的SQL分成多個簡單SQL并執行,查看具體那個字段會慢,區分度不高。
EXPLAIN
顯示SQL如何使用索引的執行計劃。
執行計劃的參數:
table 顯示這一行的數據是關于哪張表的
type 顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL
possible_keys 顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句
key 實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len 使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref 顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows 掃描請求數據的行數
Extra 關于MYSQL如何解析查詢的額外信息
PROFILE
顯示SQL執行消耗系統資源的信息。
查詢執行的過程
MySQL客戶端/服務器通信協議是“半雙工”的。客服端/服務器端都可以向對方發送數據,但不能同時發生。所以我們無法也無須將一個消息切成小塊獨立來發送。這種協議沒辦法進行流量控制。
客戶端發送請求的數據包大小由參數max_allowed_packet限制。如果查詢太大,服務端會拒絕接受更多的數據并拋出相應的錯誤。
服務器端返回的多個數據包,客戶端必須完整接受。
1.查詢狀態 SHOW FULL PROCESSLIST
mysql>SHOW FULL PROCESSLIST;Id User Host db Command Time State Info ------ ------ --------------- ------------ ------- ------ ------ -----------------------1 root localhost:61316 laravel_blog Query 0 (NULL) show FULL processlist 2 root localhost:61319 (NULL) Sleep 94 (NULL)對于一個連接,或者說一個線程,任何時刻都有一個狀態,該狀態表示了MySQL當前正在做什么。
2.查詢緩存
-- 查看緩存是否開啟 (query_cache_type 為 ON 表示已經開啟 mysql> show variables like '%query_cache%'; +------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | have_query_cache | YES | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 20971520 | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+----------+檢查sql是否命中緩存。命中則檢查一次用戶權限后返回,這個檢查是通過一個對大小寫敏感的哈希查找實現的。兩次查詢只要有一個字節的不同就會失敗。否則將進入下一個階段。
當sql中有不確定的數據時,則不會被緩存。例如用戶自定義函數、存儲函數、用戶變量、臨時表、mysql庫中的系統表,其查詢結果都不會被緩存。
3.查詢優化
語法解析器和預處理
MySQL通過關鍵字將sql語句進行解析,并生成一顆對應的解析樹。這個過程解析器主要通過語法規則來驗證和解析。比如sql中是否使用了錯誤的關鍵字或者關鍵字的順序是否正確等。預處理則會根據MySQL規則進一步檢查解析樹是否合法。比如檢查要查詢的數據表和數據列是否存在等。
查詢優化器
經過前面的步驟生成的語法樹被認為是合法的了,并且由優化器將其轉化成查詢計劃。多數情況下,一條查詢可以有很多種執行方式,最后都返回相應的結果。優化器的作用就是找到這其中最好的執行計劃。
MySQL使用基于成本的優化器,通過計算成本選擇其中最小的一個。通過SHOW STATUS LIKE 'Last_query_cost';查看成本。成本的最小單位是隨機讀取一個4K數據頁的成本。
MySQL的查詢優化器是一個非常復雜的部件,它使用了非常多的優化策略來生成一個最優的執行計劃:
- 重新定義關聯表的順序
- 將外連接轉化成內連接
- 使用等價變換規則
- 優化count()、min()、max()
- 預估并轉化為常數表達式
- 覆蓋索引描述
- 子查詢優化
- 提前終止查詢
- 等值傳播
- 列表IN()的比較
上面列舉了一些,隨著MySQL的不斷發展,優化器使用的優化策略也在不斷的進化。
查詢執行引擎
在完成解析和優化階段以后,MySQL會生成對應的執行計劃,查詢執行引擎根據執行計劃給出的指令逐步執行得出結果。整個執行過程的大部分操作均是通過調用存儲引擎實現的接口來完成,這些接口被稱為handler API。
查詢過程中的每一張表由一個handler實例表示。實際上,MySQL在查詢優化階段就為每一張表創建了一個handler實例,優化器可以根據這些實例的接口來獲取表的相關信息,包括表的所有列名、索引統計信息等。存儲引擎接口提供了非常豐富的功能,但其底層僅有幾十個接口,這些接口像搭積木一樣完成了一次查詢的大部分操作。
返回結果
查詢執行的最后一個階段就是將結果返回給客戶端。即使查詢不到數據,MySQL仍然會返回這個查詢的相關信息,比如該查詢影響到的行數以及執行時間等。
如果查詢緩存被打開且這個查詢可以被緩存,MySQL也會將結果存放到緩存中。
結果集返回客戶端是一個增量且逐步返回的過程。有可能MySQL在生成第一條結果時,就開始向客戶端逐步返回結果集了。這樣服務端就無須存儲太多結果而消耗過多內存,也可以讓客戶端第一時間獲得返回結果。需要注意的是,結果集中的每一行都會以一個滿足①中所描述的通信協議的數據包發送,再通過TCP協議進行傳輸,在傳輸過程中,可能對MySQL的數據包進行緩存然后批量發送。
以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨需要的可以免費分享給大家,需要戳這里PHP進階架構師>>>視頻、面試文檔免費獲取
或 者關注我每天分享技術文章
PHP架構師之路?www.zhihu.com總結
以上是生活随笔為你收集整理的mysql 慢查询过多_MySQL 慢查询优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视易精通收银服务器自动关机,视易收银系统
- 下一篇: Oracle数据导入要多久,oracle