一文說盡 MySQL 優化原理

2021-09-20 08:45:01 字數 4042 閱讀 5706

mysql邏輯架構

mysql查詢過程

很多的查詢優化工作實際上就是遵循一些原則讓mysql的優化器能夠按照預想的合理方式執行而已。

如果查詢結果可以被快取,那麼執行完成後,會將結果存入快取,也會帶來額外的系統消耗

批量插入代替迴圈單條插入

合理控制快取空間大小,一般來說其大小設定為幾十兆比較合適

可以通過sql_cache和sql_no_cache來控制某個查詢語句是否需要進行快取

mysql>

limit

10;...省略結果集

mysql>

'last_query_cost'

;+-----------------+-------------+

| variable_name   | value       |

+-----------------+-------------+

| last_query_cost | 6391.799000 |

+-----------------+-------------+

優化min()和max()函式(找某列的最小值,如果該列有索引,只需要查詢b+tree索引最左端,反之則可以找到最大值,具體原理見下文)

提前終止查詢(比如:使用limit時,查詢到滿足數量的結果集後會立即終止查詢)

優化排序(在老版本mysql會使用兩次傳輸排序,即先讀取行指標和需要排序的字段在記憶體中對其排序,然後再根據排序結果去讀取資料行,而新版本採用的是單次傳輸排序,也就是一次讀取所有的資料行,然後根據給定的列排序。對於i/o密集型應用,效率會高很多)

伺服器首先檢查查詢快取,如果命中快取,則立刻返回儲存在快取中的結果。否則進入下一階段

伺服器進行sql解析、預處理、再由優化器生成對應的執行計畫

mysql根據執行計畫,呼叫儲存引擎的api來執行查詢

將結果返回給客戶端,同時快取查詢結果

效能優化建議

不要聽信你看到的關於優化的「絕對真理」,包括本文所討論的內容,而應該是在實際的業務場景下通過測試來驗證你關於執行計畫以及響應時間的假設。

對整數型別指定寬度,比如int(11),沒有任何卵用。int使用32位(4個位元組)儲存空間,那麼它的表示範圍已經確定,所以int(1)和int(20)對於儲存和計算是相同的。

unsigned表示不允許負值,大致可以使正數的上限提高一倍。比如tinyint儲存範圍是-128 ~ 127,而unsigned tinyint儲存的範圍卻是0 - 255。

通常來講,沒有太大的必要使用decimal資料型別。即使是在需要儲存財務資料時,仍然可以使用bigint。比如需要精確到萬分之一,那麼可以將資料乘以一百萬然後使用bigint儲存。這樣可以避免浮點數計算不準確和decimal精確計算代價高的問題。

timestamp使用4個位元組儲存空間,datetime使用8個位元組儲存空間。因而,timestamp只能表示1970 - 2023年,比datetime表示的範圍小得多,而且timestamp的值因時區不同而不同。

大多數情況下沒有使用列舉型別的必要,其中乙個缺點是列舉的字串列表是固定的,新增和刪除字串(列舉選項)必須使用alter table(如果只只是在列表末尾追加元素,不需要重建表)。

schema的列不要太多。原因是儲存引擎的api工作時需要在伺服器層和儲存引擎層之間通過行緩衝格式拷貝資料,然後在伺服器層將緩衝內容解碼成各個列,這個轉換過程的代價是非常高的。如果列太多而實際使用的列又很少的話,有可能會導致cpu占用過高。

大表alter table非常耗時,mysql執行大部分修改表結果操作的方法是用新的結構建立乙個張空表,從舊表中查出所有的資料插入新錶,然後再刪除舊表。尤其當記憶體不足而表又很大,而且還有很大索引的情況下,耗時更久。當然有一些奇技淫巧可以解決這個問題,有興趣可自行查閱。

create

table

varchar

(50not

null

varchar

(50not

null

date

notnull

,gender enum(`m`

,`f`

notnull

,key

(last_name,first_name,dob)

);

select

from

whereid1

5

select

from

where1or

1

select

from

where

1union

select

from

where

1and

1

當出現多個索引做聯合操作時(多個or條件),對結果集的合併、排序等操作需要耗費大量的cpu和記憶體資源,特別是當其中的某些索引的選擇性不高,需要返回合併大量資料時,查詢成本更高。所以這種情況下還不如走全表掃瞄。

select

from

where

2and

584

select

count

(distinct

ascount

(distinct

ascount

from

select

from

where

1and

0

select

from

user

where

'2017-04-01'

andbetween

18and

30;

索引是有按照列值順序儲存的,對於i/o密集型的範圍查詢要比隨機從磁碟讀取每一行資料的io要少的多

// 最左列為常數,索引:(date,staff_id,customer_id)

select

from

where

date

'2015-06-01'

order

by

確保任何的group by和order by中的表示式只涉及到乙個表中的列,這樣mysql才有可能使用索引來優化。

select

from

inner

join

using

(c)where

in,6

)

outer_iterator = select a.xx,a.c from a where a.xx in (5

,6);

outer_row = outer_iterator.next

;while

(outer_row)

outer_row = outer_iterator.next

;}

select

from

order

bylimit

50,5

;

select

inner

join

from

order

bylimit

50,5

asusing

(film_id);

select

idfrom

limit

1000010;

改為:select

idfrom

where

id10000

limit

10;

join本身也挺方便的,直接查詢就好了,為什麼還需要檢視呢?

一文讀懂mysql索引底層原理

mysql官方對索引的定義為 索引是幫助mysql高效獲取資料的資料結構,簡單來說 索引就是資料結構.資料庫的底層索引是用b樹和b 樹實現的,但是為什麼使用的是它們,為什麼不用紅黑樹?紅黑樹等資料結構也可以用來實現索引,但是檔案系統以及資料庫系統普遍採用b tree b tree作為索引結構.這是因...

一文詳解 I O 優化

在沒有 dma 技術之前,i o過程是這樣的 cpu 發出對應的指令給磁碟控制器,飯後返回。磁碟控制器收到指令後,於是就開始準備資料,會把資料放入到磁碟控制器的內部緩衝區中,然後產生乙個中斷。cpu 收到中斷訊號後,停下手頭的工作,接著把磁碟控制器的緩衝區的資料一次乙個位元組地讀進自己的暫存器,然後...

一文回顧mysql

索引事務 鎖機制主要介紹myisam和innodb,在伺服器中,用於儲存資料會生成以下檔案 innodb採用的是b 樹作為索引的資料結構 經常用的列優先 最左匹配原則 離散型高的列優先 離散度高原則 寬度小的列優先 最小空間原則 提高每個節點的路數 索引按場景建,建多了會導致增刪改的時候,需要維護索...