MySQL8.0性能優化
MySQL8.0 引擎:
來看看MySQL8提供的引擎:
常用引擎:
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