天天看點

mysql的資料庫優化方案_MySql資料庫優化方案

1.選擇InnoDB引擎

理由:

(1)支援事務

InnoDB與傳統的ISAM與MyISAM相比,InnoDB的最大特色就是支援了ACID相容的事務(Transaction)功能,類似于PostgreSQL。

(2)支援行鎖

MyISAM隻支援表級鎖,使用者在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert并發的情況下,可以在表的尾部插入新的資料。

InnoDB的行鎖,隻是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

2.選擇自增ID作為主鍵

在使用InnoDB存儲引擎時,如果沒有特别的需要,請永遠使用一個與業務無關的自增字段作為主鍵。

InnoDB使用聚簇索引,資料記錄本身被存于主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點内(大小為一個記憶體頁或磁盤頁)的各條資料記錄按主鍵順序存放,是以每當有一條新的記錄插入時,MySQL會根據其主鍵将其插入适當的節點和位置,如果頁面達到裝載因子(InnoDB預設為15/16),則開辟一個新的頁(節點)。如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到目前索引節點的後續位置,當一頁寫滿,就會自動開辟一個新的頁。這樣就會形成一個緊湊的索引結構,近似順序填滿。由于每次插入時也不需要移動已有資料,是以效率很高,也不會增加很多開銷在維護索引上。

如果使用非自增主鍵(如果身份證号或學号等),由于每次插入主鍵的值近似于随機,是以每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不為了将新記錄插到合适位置而移動資料,甚至目标頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷,同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,後續不得不通過OPTIMIZE TABLE來重建表并優化填充頁面。

InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是位址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。是以不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。

3.單表字段總的Size不宜過大

主鍵(即聚簇索引)的B+樹上葉子節點與資料存放在一起。每一個節點在資料庫中都是一個頁,頁是innodb磁盤管理最小的機關,innodb每個頁的大小是16K。單行資料越小,每個頁存儲的行數就越多。

如何計算目前表的理論上分表的最大值

在開始這一塊之前,我們需要了解以下幾個資訊:

① 每一個節點在資料庫中都是一個頁,頁是innodb磁盤管理最小的機關,innodb每個頁的大小是16K,且不可更改。常見的類型有:資料頁 B-tree Node;undo頁 Undo Log Page;系統頁 System Page;事務資料頁 Transaction system Page;插入緩沖位圖頁 Insert Buffer Bitmap;插入緩沖空閑清單頁 Insert Buffer freeBitmap;未壓縮的二進制大對象頁Uncompressed BLOB Page;壓縮的二進制大對象頁 Compressed BLOB Page。

② 每個key後有個頁号4B,還有6B的其他資料(參考《MySQL技術内幕:InnoDB存儲引擎》P193的頁面資料)

③ 裝載因子(InnoDB預設為15/16)

以下是針對單行資料在300bit大小的資料計算步驟:

�①索引節點:(16000/(8+4+6))15/16=833.33個

�②葉子節點:假設單行資料300b,計算為(16000/(300+8+4+6))15/16=47.17

�③總共三層B+樹可存儲資料量為:833.33833.3347.17=32756682條資料

根據以上計算步驟,300b資料量情況下理論單表三度索引資料大概是3275w資料

3.聯合索引的最左比對原則

與b+樹檢索是比較key相關

4.union、in、or 都能夠命中索引,建議使用 in

or:新版的 MySQL 能夠命中索引

5.負向條件查詢不能使用索引,可以優化為 in 查詢

負向條件有:!=、<>、not in、not exists、not like 等。

6.把計算放到業務層而不是資料庫層

7.強制類型轉換會全表掃描

where語句中字段與比對值類型不同時會觸發強制類型轉換。

8.更新十分頻繁、資料區分度不高的字段上不宜建立索引

更新索引字段值會變更 B+ 樹,更新頻繁的字段建立索引會大大降低資料庫性能。

“性别”這種區分度不大的屬性,建立索引是沒有什麼意義的,不能有效過濾資料,性能與全表掃描類似。

一般區分度在80%以上的時候就可以建立索引,區分度可以使用 count(distinct(列名))/count(*) 來計算。

9.如果有 order by、group by 的場景,請注意利用索引的有序性

order by 最後的字段是組合索引的一部分,并且放在索引組合順序的最後,避免出現 file_sort 的情況,影響查詢性能。

例如對于語句 where a=? and b=? order by c,可以建立聯合索引(a,b,c)。

如果索引中有範圍查找,那麼索引有序性無法利用,如 WHERE a>10 ORDER BY b;,索引(a,b)無法排序。

10.對于列的值比較長的索引,使用短索引(又叫字首索引)來優化索引

11.建立索引的列,不允許為 null

12.單表索引建議控制在5個以内,單索引字段數不允許超過5個

13.如果明确知道隻有一條結果傳回,limit 1 能夠提高效率