# mysql查詢優化
* [請簡述專案中優化mysql語句執行效率的方法,從哪些方面入手,sql語句效能如何分析?](
* [分析查詢速度](
* [優化查詢過程中的資料訪問](
* [優化長難的查詢語句](
* [優化特定型別的查詢語句](
* [優化`count()`查詢](
* [優化關聯查詢](
* [優化子查詢](
* [優化`group by`和`distinct`](
* [優化`limit`子句](
* [優化`union`](
# 請簡述專案中優化mysql語句執行效率的方法,從哪些方面入手,sql語句效能如何分析?
# 分析查詢速度
* 記錄慢查詢日誌
分析查詢日誌,使用`pt-query-digest`工具進行分析
* 使用`show profile`
set profiling=1; # 伺服器上執行的所有語句會檢測消耗的時間、存到臨時表中
`show profiles # 所有的sql語句執行記錄`
`show profile for query 臨時表id # 查執行id的sql語句`
mysql> set profiling=1;
query ok, 0 rows affected
mysql> select * from user;
| id | name | age |
| 1 | jack | 23 |
1 row in set
mysql> show profiles;
| query_id | duration | query |
| 1 | 8.675e-5 | set profiling=1 |
| 2| 0.000197 | select * from user |
10 rows in set
mysql> show profile for query 2;
| status | duration |
| starting | 4.3e-5 |
| checking permissions | 7e-6 |
| opening tables | 1.8e-5 |
| system lock | 1e-5 |
| init | 1.4e-5 |
| optimizing | 4e-6 |
| statistics | 3.1e-5 |
| preparing | 1e-5 |
| executing | 2e-6 |
| sending data | 1e-5 |
| end | 3e-6 |
| query end | 2e-6 |
| closing tables | 5e-6 |
| freeing items | 3.5e-5 |
| logging slow query | 3e-6 |
| cleaning up | 2e-6 |
16 rows in set
* show status
`show status`會返回一些計數器,`show global status`檢視伺服器級別的所有計數。
* show processlist
觀察是否有大量的執行緒處於不正常的狀態或特徵。
* explain
分析單條的sql語句
mysql> explain select * from user;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
| 1 | ****** | user | system | null | null | null | null | 1 | |
1 row in set
> explain它有乙個別名`desc`,所以使用`desc select * from user;`查詢到的結果與上面的一樣。
# 優化查詢過程中的資料訪問
* 資料太多會導致查詢效能下降。
* 確定應用程式是否在檢索大量超過需要的資料,可能太多行或列。
* 確認mysql伺服器是否在分析大量不必要的資料行
**避免使用以下sql語句**
* 查詢不需要的記錄,使用`limit`解決
* 多表管理返回全部列,需要制定列,[如a.id](等
* 總是取出全部列,`select *`會讓優化器無法完成索引覆蓋掃瞄優化
* 重複查詢相同的資料,可以使用快取,下次直接讀取快取
**是否在掃瞄額外的記錄**
使用`explain`來進行分析,如果發現查詢需要掃瞄大量的資料但是只返回少數的行,可以通過如下技巧去優化:
* 使用索引覆蓋掃瞄,把所有的列都放在索引中。
* 改變資料庫和表的結構,修改資料表正規化
* 重寫sql語句,讓優化器可以以最優的方式執行查詢
# 優化長難的查詢語句
使用盡可能小的查詢是好的,但有時將乙個大的查詢分解成多個小的查詢是很有必要的。
* **切分查詢**
將乙個大的查詢分為多個小的相同的查詢
一次性刪除1000萬的資料比一次刪除1萬,暫停一會兒在執行刪除1萬條資料要較少更多的伺服器開銷。
* **分解關聯查詢**
可以將一條關聯語句分解成多個sql語句執行
讓快取的效率更高
執行單個查詢可以減少鎖的競爭
在應用層做關聯可以更容易對資料庫進行拆分
# 優化特定型別的查詢語句
## 優化`count()`查詢
* `count(*)`占用的`*`會忽略所有的列,直接統計所有的列數,因此不要使用`count(列名)`
* myisam中`沒有任何where條件的count(* )`查詢速度非常快
* `有where條件`時,myisam的count統計不一定比其他表引擎快
優化:* 可以使用`explain`查詢近似值,用近似值代替`count(*)`
* 增加彙總表
* 使用快取
## 優化關聯查詢
* 確定on或者using子句的列上有索引;
* 確保`group by`和`order by`中只有乙個表中的列,這樣mysql才有可能使用索引;
## 優化子查詢
盡量使用關聯查詢替代
## 優化`group by`和`distinct`
* 使用**索引**來優化
* 關聯查詢中,使用**標識列**(主鍵列)進行分組的效率會更高
* 如果不需要`order by`,進行`group by`時使用`order by null`,mysql不會進行檔案排序
* `with rollup`超級劇和,可以挪到應用程式處理
## 優化`limit`子句
`limit`偏移量大的時候,查詢效率較低。
方案:* 記錄上一次查詢的最大id,下次查詢時直接根據id來查詢(還是使用limit查詢,不過加乙個where條件,id > id)
## 優化`union`
`union all`的效率高於`union`。
關於 0x3f3f3f3f 的問題
0x3f3f3f3f是乙個很有用的數值,它是滿足以下兩個條件的最大整數。1 整數的兩倍不超過 0x7f7f7f7f,即int能表示的最大正整數。2 整數的每8位 每個位元組 都是相同的。我們在程式設計中經常需要使用 memset a,val,sizeof a 初始化乙個陣列a,該語句把數值 val ...
0x3f3f3f3f(無窮大數)
一般定義無窮大數都是inf 99999999,或者0x7f ff ff ff,但是有的時候inf過大,雖然保證了沒有數超過它,但是在需要加上乙個數的時候,inf a可能會導致溢位,最終變成乙個負數。而0x3f3f3f3f的數量級也1e9的,一般題不會給超過1e9的數 在把它當成無窮大的時候,兩個0x...
Python3物件導向 3 異常(3)異常作用
當丟擲異常時,看起來好像立即停止了程式的執行。丟擲異常之後的所有 都不會執行,除非處理了這一異常,程式將會退出並給出錯誤資訊。def no return print i am about to raise an exception raise exception this is always rai...