MySQL8.0效能優化

Sol·wang發表於2021-06-19

MySQL8.0 引擎:

來看看MySQL8提供的引擎:
MySQL8.0 引擎

常用引擎:

InnoDB:支援事務,行級鎖,外來鍵,崩潰修復,多版本併發控制;讀寫效率相對較差,記憶體使用相對較高,佔用資料空間相對較大。

MyISAM:不支援事務,不支援外來鍵,僅支援非聚集索引,支援全文索引,僅支援到表級鎖,支援資料壓縮,佔用空間相對小,記憶體使用相對較低,讀寫效能相對極佳。

Memory:依賴於記憶體空間,資料處理速度快,僅支援到表級鎖。

應用場景:

InnoDB:依賴於 事務,回滾,併發,大資料量,外來鍵,行級鎖 的場景。

MyISAM:過多的大資料量的頻繁的查詢優勢。

Memory:臨時性的,大資料量表的查詢優勢。

在建立表的時候,可依據應用場景選擇合適的引擎。

 

分表 / 拆表 / 分庫 / 分盤

分表:解決單表資料量過大的效能瓶頸,小範圍的資料處理,避免過多資料掃描;可按業務型別資料、時間跨度等實際場景分表。

拆表:按場景合理的將大表分為多個小表來降低鎖競爭

分庫:分例項分別各自處理,量與效能的分散優化處理,欠缺的事務一致性,可按實際場景合理分庫。

分盤:主要解決磁碟IO瓶頸,多磁碟分散並行執行。

 

索引

索引分類

普通索引:無限制

主鍵索引:表中只能有一個,不能為NULL

唯一索引:值不能重複

全文索引:僅MyISAM支援,僅支援 char、varchar、text 型別

組合索引:多列一起建立的合併索引,非單列分別建立的索引

 

所有儲存引擎對每個表至少支援了16個索引。

 

索引設計原則:

為經常需要排序、分組或聯合操作的欄位建立索引,經常需要使用 order by、group by、distinct、uninon 等的操作欄位

為經常查詢出的列建立索引,為經常作為查詢條件的欄位建立索引

推薦長度較少的列建索引,推薦列使用固定長度。

過多的索引建立對錶資料變更操作的效能下降的影響

刪除不再使用或很少使用的索引,減少索引對更新時的影響

索引覆蓋,索引下推,避免回表查詢(以下介紹)

 

索引命中:

依據索引查詢,查詢條件常以索引列開始

組合索引的最左原則:必須以組合索引列的首列開始的條件查詢,按序依次。

索引覆蓋,推薦要查詢出的欄位全部為索引列。假如頁面列表呈現出個別主要的欄位內容的場景;具體的詳細內容在詳細頁呈現,透過主鍵查詢單條資料。

避免回表查詢:MySQL首先查出帶索引的列資料,再透過主鍵列去查詢非索引列的資料資訊,把兩次查詢的資料組合後返回客戶端。所以推薦索引覆蓋。

 

指令碼優化

儘量避免巢狀子查詢,改用JOIN方式。

儘量減少 查詢中的全表掃描次數 ,尤其是對於大表,如採用EXISTS、WHERE的條件順序等。

避免欄位以難以理解的方式轉換查詢,採用更為合理的轉換方式。

去除不必要的括號,避免複雜邏輯查詢。如 (1=1 and (b>a and b=c)) and a=5 推薦為 b>5 and b=c and a=5

簡化減少WHERE條件範圍區間的重疊部分。如 (key1 < 'abc' and 1=1) or (key1 < 'bar') or (false) 推薦為 key1 < 'bar'

避免WHERE後用函式臨時的計算,可事先生成結果列或虛擬列。

推薦WHERE中首次出現的IS NULL賦予更大的作用,因為MySQL8僅對首次出現的IS NULL做大量優化。

某些場景對索引的失效或破壞,FORCE INDEX:指明優先使用的索引並生效;常用於JOIN。

IN的巢狀查詢改為EXISTS的巢狀查詢。

INNER JOIN 時,STRAIGHT_JOIN 指明優先檢索的主表,使其特定場景中達到我們的預期效果。

被巢狀的查詢更多的篩選和處理,使其減少外表查詢的資料基數。

批量INSERT使用包含多個VALUES列表的語句一次插入多行,量越大效果越明顯。(加大 bulk_insert_buffer_size、Max_allowed_packet、Net_buffer_length 的值,滿足更大量的處理)

推薦預設值列,非顯示的插入減少必要的解析。

某些場景下,replace into 的使用,代替 insert/update,成為單一的原子操作。

SQL片段WITH AS的運用,Memory Table 的利用。

查詢僅返回需要的欄位,避免 *,避免回表查詢;僅返回需要的資料量。

 

InnoDB緩衝池

一個稱為緩衝池的儲存區域,用於在記憶體中快取資料和索引,利用它將經常訪問的資料儲存在記憶體中,減少了SQL執行及磁碟IO的資源消耗。為了更多的需要暫存空間,滿足更大資料量的暫存。

引數設定:

innodb_buffer_pool_size:緩衝池的承載總量,建議設為系統記憶體的50%-70%

innodb_buffer_pool_chunk_size:緩衝池每塊大小,預設128M

innodb_buffer_pool_instances:多執行緒緩衝池例項並行執行,預設1例項,最大64例項

設定規則:

innodb_buffer_pool_size = (innodb_buffer_pool_chunk_size * {N}塊 )* innodb_buffer_pool_instances

也就是說,innodb_buffer_pool_size 必須是 innodb_buffer_pool_chunk_size 的倍數

舉例說明:

符合的例子:innodb_buffer_pool_size=8G,innodb_buffer_pool_chunk_size=128M,innodb_buffer_pool_instances=16

不符的例子:innodb_buffer_pool_size=9G,innodb_buffer_pool_chunk_size=128M,innodb_buffer_pool_instances=16

對於以上非倍數的狀況:

MySQL會自動將 innodb_buffer_pool_size 調整為 innodb_buffer_pool_chunk_size 的倍數;所以會變為 innodb_buffer_pool_size = 10G

執行機制:

緩衝區分為 熱資料區 / 冷資料區,兩者空間佔比約為 7/3,每區中的資料集依使用頻率按順序依次排列。

當一個新的查詢結果出現後,首先考慮存放到冷資料區,當冷資料區的結果集使用達到一定頻率,會被改存到熱資料區,使用頻率最好的資料集會被存放到熱區的首位,當然也有熱區轉到冷區的狀況。

 

MySQL8 去除了 [查詢快取] query_cache_type、query_cache_size、query_cache_limit

 

連線池

MySQL聯結器中的連線池,用以提高資料庫密集型應用程式的效能和可擴充套件性。預設啟用。MySQL聯結器負責管理連線池中的多個連線,自動建立、開啟、關閉和破壞連線,多個連線的建立,可滿足多客戶端的頻繁連線,連線的重複使用獲得最佳效能。
MySQL聯結器 每三分鐘執行一次後臺作業,並從池中刪除閒置(未使用)超過三分鐘的連線。池清理釋放客戶端和伺服器端的資源。這是因為在客戶端每個連線都使用一個Socket,而在伺服器端每個連線都使用一個Socket和一個執行緒。

透過連線字串引數對連線池的設定調整其效能特點:
  • 開啟連線池:Pooling=true,預設開啟
  • 複用時重置連線狀態:ConnectionReset=True
  • 保持連線設定:CacheServerProperties=True
  • 連線超時回收(秒):ConnectionLifeTime=300
  • 支援的最大連線數量:Max Pool Size=100
  • 保持最小的連線數量:Min Pool Size=10

 

日誌

MySQL在執行時,會有各種不同日誌的記錄,大量的各種型別的日誌產生,會對資源的開銷產生嚴重的影響,必要的時候我們選擇性的開啟。但在生產環境時,有些日誌並不是必須,以下列出MySQL各種日誌資訊:

  • 錯誤日誌:啟動、關閉、執行時 產生的異常記錄,建議開啟,設定 log_error
  • 查詢日誌:客戶端連線和執行的指令碼,建議關閉,設定 general_log
  • 慢查詢日誌:記錄超時的查詢,記錄不適用索引的查詢等,建議關閉,設定 slow_query_log
  • 二進位制日誌:用於資料同步複製,需傳送的資料日誌,多用於叢集,如需開啟,設定 log_bin
  • 中繼日誌:用於資料同步複製時,接收到的資料日誌,多用於叢集,如需開啟,設定 relay_log

 

相關文章