SQL語句慢查詢的緣由有多種,如:
1)數據方面:
須要查詢的表數據量太大致使性能降低;
是否向數據庫請求了不須要的數據行或數據列;
MySQL是否在掃描額外的記錄mysql
2)SQL語句太過於冗餘面試
3)等sql
下面咱們列出一下分析SQL查詢慢的一些方法:數據庫
一、記錄慢查詢日誌緩存
分析查詢日誌,不要直接打開慢查詢日誌進行分析,這樣比較浪費時間和精力,可使用pt-query-digest工具進行分析。服務器
二、使用show profile
使用步驟:架構
1)開啓,服務器上執行的全部語句會檢測消耗的時間,存到臨時表中 set profiling = 1; 2)進行須要分析的SQL查詢 ... 3)show profiles 4)show profile for query 臨時表id
如:工具
mysql> set profiling = 1; Query OK, 0 rows affected (0.00 sec) mysql> show profiles; Empty set (0.00 sec) mysql> select * from a; +------+--------+ | id | name | +------+--------+ | 1 | nosee | | 2 | chan | | 3 | cheese | | 4 | xyz | +------+--------+ 4 rows in set (0.00 sec) mysql> show profiles; +----------+------------+-----------------+ | Query_ID | Duration | Query | +----------+------------+-----------------+ | 1 | 0.00054875 | select * from a | +----------+------------+-----------------+ 1 row in set (0.00 sec) mysql> show profile for query 1; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000063 | | checking permissions | 0.000013 | | Opening tables | 0.000050 | | System lock | 0.000018 | | init | 0.000023 | | optimizing | 0.000007 | | statistics | 0.000018 | | preparing | 0.000010 | | executing | 0.000004 | | Sending data | 0.000104 | | end | 0.000006 | | query end | 0.000004 | | closing tables | 0.000008 | | freeing items | 0.000196 | | logging slow query | 0.000022 | | cleaning up | 0.000006 | +----------------------+----------+ 16 rows in set (0.00 sec)
三、使用show status性能
show status會返回一些計數器,show global status 查看服務器級別的全部計數。有時根據這些計數,能夠猜想出哪些操做代價較高或消耗時間多。學習
四、使用explain
explain命令用於分析單條SQL語句,是查看優化器如何決定執行查詢的主要方法。
如:
mysql> explain select id from a where id =3\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: a type: ref possible_keys: id key: id key_len: 5 ref: const rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec)
關於EXPLAIN更詳細的內容請查看下一篇文章。
當但願MySQL可以以更高的性能運行查詢時,最好的辦法就是弄清楚MySQL是如何優化和執行查詢的。
當咱們向MySQL發送一個請求時,MySQL到底作了些什麼,下面咱們經過一個簡單的圖解來進行分析:
1)客戶端發送一條查詢給服務器。
2)服務器先檢查查詢緩存,若是命中了緩存,則馬上返回存儲在緩存中的結果,不然進入下一階段。
3)服務器進行SQL解析、預處理,再由優化器生成對應的執行計劃。
4)MySQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢。
5)將結果返回給客戶端。
上面的每一步都比想象的要複雜,這裏將不深刻討論。
一、定位問題
訪問數據太多致使查詢性能降低。
肯定應用程序是否在檢索大量超過須要的數據,多是太多行或列。確認MySQL服務器是否在分析大量沒必要要的數據行。
二、避免使用以下SQL語句
1)查詢不須要的數據,使用limit解決
2)多表關聯返回所有列,指定如A.id, A.name, B.age
3)老是取出所有列,SELECT *
會讓優化器沒法完成索引覆蓋掃描的優化
4)重複查詢相同的數據,能夠緩存數據,下次直接讀取緩存
三、是否在掃描額外的記錄
使用explain來進行分析,若是發現查詢須要掃描大量的數據但只返回少數的行,能夠經過以下技巧去優化:
1)使用索引覆蓋掃描,把全部用的列都放到索引中,這樣存儲引擎不須要回表獲取對應行就能夠返回結果
2)改變數據庫和表的結構,修改數據表範式
3)重寫SQL語句,讓優化器能夠以更優的方式執行查詢
MySQL內部每秒能掃描內存中上百萬行數據,相比之下,響應數據給客戶端就要慢得多。使用盡量少的查詢是最好的,但有時將一個大的查詢分解爲多個小的查詢也是頗有必要的。
一、切分查詢
將一個大的查詢分爲多個小的相同的查詢。如一次性刪除1000萬的數據,要比一次刪除1萬暫停一會的方案更加損耗服務器開銷。
二、分解關聯查詢
1)能夠將一條關聯語句分解成多條SQL來執行
2)執行單個查詢能夠減小鎖的競爭
3)在應用層作關聯能夠更容易對數據庫進行拆分
一、優化count()查詢
1)count(*)中的*會忽略全部的列,直接統計全部列數,所以不要使用count(列名)。MyISAM中,沒有任何WHERE條件的count(*)很是快。
2)可使用explain查詢近似值,用近似值替代count(*)
3)增長彙總表
4)使用緩存
二、優化關聯查詢
1)肯定ON或USING子句的列上有索引
2)確保GROUP BY和ORDER BY中只有一個表中的列,這樣MySQL纔有可能使用索引
三、優化子查詢
儘量使用關聯查詢來替代
四、優化GROUP BY和DISTINCY
1)這兩種查詢都可使用索引來優化,是最有效的優化方法
2)關聯查詢中,使用標識列進行分組的效率會更高
3)若是不須要ORDER BY,進行GROUP BY時使用ORDER BY NULL,MySQL不會進行文件排序
4)WITH ROLLUP超級聚合,能夠挪到應用程序處理
五、優化LIMIT分頁
LIMIT偏移量大的時候,查詢效率較低。能夠記錄上次查詢的最大ID,下次查詢時直接根據該ID來查詢。
六、優化UNION查詢
UNION ALL的效率高於UNION。
一、請簡述項目中優化SQL語句執行效率的方法,從哪些方面,SQL語句性能如何分析?
考官考點:
1)查找分析查詢速度慢的緣由
2)優化查詢過程當中的數據訪問
3)優化長難的查詢語句
4)優化特定類型的查詢語句
對於此類問題,先說明如何定位低效率SQL語句,而後根據SQL語句可能低效的緣由作排查,先從索引着手,若是索引沒問題,考慮以上幾個方面:數據訪問的問題、長難查詢句的問題、仍是一些特定類型優化的問題,逐步排除。
以爲不錯請點贊支持,歡迎留言或進個人我的羣855801563領取【架構資料專題目合集90期】、【BATJTMD大廠JAVA面試真題1000+】,本羣專用於學習交流技術、分享面試機會,拒絕廣告,我也會在羣內不按期答題、探討