高性能MySQL06-查詢優化(慢查詢)

1、分析緣由

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更詳細的內容請查看下一篇文章。

2、查詢執行原理

當但願MySQL可以以更高的性能運行查詢時,最好的辦法就是弄清楚MySQL是如何優化和執行查詢的。

當咱們向MySQL發送一個請求時,MySQL到底作了些什麼,下面咱們經過一個簡單的圖解來進行分析:

1)客戶端發送一條查詢給服務器。
2)服務器先檢查查詢緩存,若是命中了緩存,則馬上返回存儲在緩存中的結果,不然進入下一階段。
3)服務器進行SQL解析、預處理,再由優化器生成對應的執行計劃。
4)MySQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢。
5)將結果返回給客戶端。

上面的每一步都比想象的要複雜,這裏將不深刻討論。

3、優化查詢過程當中的數據訪問

一、定位問題

訪問數據太多致使查詢性能降低。

肯定應用程序是否在檢索大量超過須要的數據,多是太多行或列。確認MySQL服務器是否在分析大量沒必要要的數據行。

二、避免使用以下SQL語句

1)查詢不須要的數據,使用limit解決
2)多表關聯返回所有列,指定如A.id, A.name, B.age
3)老是取出所有列,SELECT *會讓優化器沒法完成索引覆蓋掃描的優化
4)重複查詢相同的數據,能夠緩存數據,下次直接讀取緩存

三、是否在掃描額外的記錄

使用explain來進行分析,若是發現查詢須要掃描大量的數據但只返回少數的行,能夠經過以下技巧去優化:
1)使用索引覆蓋掃描,把全部用的列都放到索引中,這樣存儲引擎不須要回表獲取對應行就能夠返回結果
2)改變數據庫和表的結構,修改數據表範式
3)重寫SQL語句,讓優化器能夠以更優的方式執行查詢

4、優化長難的查詢語句

MySQL內部每秒能掃描內存中上百萬行數據,相比之下,響應數據給客戶端就要慢得多。使用盡量少的查詢是最好的,但有時將一個大的查詢分解爲多個小的查詢也是頗有必要的。

一、切分查詢

將一個大的查詢分爲多個小的相同的查詢。如一次性刪除1000萬的數據,要比一次刪除1萬暫停一會的方案更加損耗服務器開銷。

二、分解關聯查詢

1)能夠將一條關聯語句分解成多條SQL來執行
2)執行單個查詢能夠減小鎖的競爭
3)在應用層作關聯能夠更容易對數據庫進行拆分

5、優化特定類型的查詢語句

一、優化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+】,本羣專用於學習交流技術、分享面試機會,拒絕廣告,我也會在羣內不按期答題、探討

相關文章
相關標籤/搜索