3erow mysql MySQL查詢優化

2021-10-18 12:59:07 字數 3550 閱讀 6675

# 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...