前言:為什么說是極致優化,不要小瞧上面的3000萬說的比較少,為啥,因為我們知道數據量不能代表一切,還要看字段的長度,和字段數量,這3000萬數據 分化在60張表里面,核心表6 7張每張數據量大約在300w-800w,字段長度在60-200不等,並且大部分表內部包涵超長文本。這樣你還覺得慢嗎。
背景:數據庫遷移,sqlserver 將數據遷移至mysql。平行遷移。公司切換數據庫。
優化方向一:(代碼級別優化)
優化點1:批量寫入(大家應該都知道,但是這個批量寫入還略有不同,區別在下面的優化點慢慢看)
優化點2:批量寫入數據庫使用的方式,選擇了sqlsession(預處理語句)
優化點3:多線程執行操作(將數據庫性能發揮到極限)
優化點4:滾動查詢(查詢效率極高,是普通分頁查詢的10倍以上)
優化方向二:(數據庫引擎參數配置優化)
優化點1:global innodb_flush_log_at_trx_commit(事務提交時 日志設置 效果明顯)
優化點2:max_connections 最大連接數 ,這個要綜合考慮各種情況包涵服務器節點數 線程數據,服務器核心數 等資源分配情況
優化點3:global bulk_insert_buffer_size (插入緩沖區)
優化點4:innodb_buffer_pool_size(InnoDB緩沖池)
優化點5:innodb_autoextend_increment(tablespace 空間)
優化方式三:(啟動分配優化 jvm)
優化點1: -Xmx2g -Xms2g -Xss1m 提前分配一下資源 啟動內存等
優化方式四:(服務器方向優化,分布式多節點)
優化點1:多節點部署程序,將性能跑到極限
優化點5:(mysql流寫入)
優化點1:目前 最快的寫入方式 比較極限了
主干(細講各個優化點)
優化方向一:(代碼級別優化)
優化點1:批量寫入
把sql當做一個字符串,提前拼接好 一次批量的條數要根據數量,數據大小,字段長度決定,我這次優化一次50條,因為字段太多,長度太大,大約等於普通表10個字段的 200-500條左右,這個需要自己測試,說一下測試標准
如何看多少條合適,
測試 50 條 100條 200條 500條 1000條 打印出 每次執行的時間,就能看出你的表多少條合適了,當然復雜的場景可以寫程序自動判斷批量的條數,每一張表 動態設定批量的條數。需要自己把我一個臨界點。多次測試你才能得到
你想要的的答案。
優化點2:批量寫入數據庫使用的方式,選擇了sqlsession(預處理語句)
為啥使用sqlsession 而不是使用mybatis 的普通批量。因為需要設置預編譯處理。當然你如果在配置文件配置好 也是可以用mybatis for 去批量寫入的。
核心點在於 設置openSession(ExecutorType.BATCH); 批量預處理。這樣大概是mybatis默認的單條處理的5-7倍以上的效率
mybatis 默認 SIMPLE
還有 REUSE, BATCH
SIMPLE:它為每個語句的執行創建一個新的預處理語句。
REUSE:這個執行器類型會復用預處理語句
BATCH:這個執行器會批量執行所有更新語句
我選擇用 BATCH; 並且是沒三萬條數據 開啟關閉一次sqlsession, 當然開啟關閉sqlsession 影響不大。對效率。 建議一次開啟關閉 也不要處理太多條數據了。
優化點3:多線程執行操作(將數據庫性能發揮到極限)
使用線程池 去執行批量寫入,建議根據服務其核心數 以及代碼耗時等各種因數考慮開啟的寫入線程數量
沒個線程獨立管理一個sqlsession。單次執行3萬條,循環批量寫入。邏輯可以自己控制
我開啟的是15個線程 服務器配置 4核心 代碼跑起來 使用率在370%左右 cpu
優化點4:滾動查詢
什么是滾動查詢,不知道大家有沒有發現 一張表如果有1000萬條數據 你用普通分頁查詢,一開始很快,越到后面越慢。為了避免這種低效率分頁。轉而使用了滾動查詢
核心依賴 每張表的自增id 每次查詢 where條件是 例如 查詢第900萬開始 后 100條數據 那么就是 where id>9000000 order by id desc limit 100 這樣的效率是非常高的,id等於字典里面的目錄,
直接把閱讀指針 放到9000000萬的點, 在這里面 取出前100條數據。 而不是 需要把前900萬條數據先 翻一遍 才知道 哦 原來那不是我想要的。 向我寫的代碼 是一線程任務形式提交,每個任務都會有起始id,和 結束id,所以我還會在
條件加上where id>9000000 and id<9001000 order by id desc limit 100 下一次查詢的時候取出 本次查詢最大id 當做 起始id 繼續往下查。
優化方向二:(數據庫引擎參數配置優化)
優化點1:global innodb_flush_log_at_trx_commit(事務提交時 日志設置 效果明顯)
0:事務提交時,不做日志寫入操作,而是每秒鍾將log buffer中的日志寫入文件並且flush磁盤一次。
1:每秒鍾或者事務提交時,都會引起日志寫入和flush磁盤操作,這樣設計也是最安全的。
2:每次事務提交時,進行日志寫入,但此時沒有flush磁盤操作,而是在每秒鍾時進行flush磁盤操作。
建議根據情況具體考慮,需要炒雞絲管理員權限,0的效率最高 但是有一定風險。我選的0 遷移后又改為1
優化點2:max_connections 最大連接數 ,這個要綜合考慮各種情況包涵服務器節點數 線程數據,服務器核心數 等資源分配情況
我給調到了200 其實並不大這點連接 mysql 絕對扛得住。 我一個節點 15個線程再跑,最多一個節點占用15個連接 8個節點 大約是120連接數。 考慮 平時還有別人使用所以我 設置為 200 這個大家根據自己的情況去設置。
但是也不建議調到太高。
優化點3:innodb_buffer_pool_size(InnoDB緩沖池)
- 數據緩存
- 索引緩存
- 緩沖 – 更改的數據(通常稱為臟數據)在被刷新到硬盤之前先存放到緩沖
- 存儲內部結構 – 一些結構如自適應哈希索引或者行鎖也都存儲在InnoDB緩沖池
如果用Innodb,那么這是一個重要變量。相對於MyISAM來說,Innodb對於buffer size更敏感。
MySIAM可能對於大數據量使用默認的key_buffer_size也還好,但Innodb在大數據量時用默認值就感覺在爬了。
Innodb的緩沖池會緩存數據和索引,所以不需要給系統的緩存留空間,如果只用Innodb,可以把這個值設為內存的70%-80%。
和 key_buffer相同,如果數據量比較小也不怎么增加,那么不要把這個值設太高也可以提高內存的使用率。
優化點4:innodb_autoextend_increment (tablespace 空間)
此配置項作用主要是當tablespace 空間已經滿了后,需要MySQL系統需要自動擴展多少空間,
每次tablespace 擴展都會讓各個SQL 處於等待狀態。增加自動擴展Size可以減少tablespace自動擴展次數。
優化點5:事務級別
事務級別調到最低。mysql默認是第三級別
會增加很高的效率 風險高 謹慎使用
優化方式三:(啟動分配優化 jvm)
優化點1: -Xmx2g 為jvm啟動時分配的內存
-Xms2g 為jvm運行過程中分配的最大內存
-Xss1m 沒個線程分配的最大內存
這些根據你自己的需要去調整吧。如果代碼不是 太費內存,起始這些參數不改也行。看需求了
優化方式四:(服務器方向優化,分布式多節點)
優化點1:多節點部署程序,將性能跑到極限
一共部署了8個節點,每個節點15個線程,每個服務器 cpu使用率 在 350-370
核心:
八個節點
通過 job 手動觸發的。八個節點一起跑,大約 我測試過
查詢效率大概單個線程 5毫秒 查詢100條數。
也就是1秒 = 一個線程 2萬條數 = 15 個線程 30萬數據 = 8各節點 240萬數據
當然這也只是理論極限,實際並沒有這么快 但是也慢不到那里去,我測試的時候最快一次 單節點 4秒鍾 查出來 50萬條數據。 當然是最快的一次 哈哈。單個節點。多個節點 查不同的表會更快
當然這種效率完全能滿足我們的查詢需求了
寫入效率 就是非常低了 大約是查詢的 10倍以上消耗的時間
大約一次耗時20-30ms
但是處理起來 1秒 = 一個線程 2000條寫入 = 15個線程 30000 寫入 = 8 個節點 24萬寫入
mysql 這個寫入效率還是可以的把 哈哈。
優化點5:(流寫入)
使用mysql 官方 自帶的流寫入
因為根據上面的分析 我們性能的瓶頸在 插入上 那么如何提升
使用mysql 的流寫入。
建議用sql 的方方式 傳遞路徑 讓mysql 去讀取數據文件,因為如果直接不往文件里面寫入
以流的方式寫入 那么需要消耗非常的內存,因為一般只有數據量大的時候才會 使用這種方式。
所以還是寫入文件合適,並且也慢不了多少。
效率 經過測試 大約在每秒鍾 40萬左右 這個數字 根據 你自身的數據大小 和mysql 緩存區配置都是有關系的。
但是這種方式 是 目前寫入最快的一種方式了。
不過 這里坑比較多。建議大家謹慎使用
高版本mysql 驅動 流寫入 有bug 一直說沒權限 低版本的能用 但是表情符號 存入不進去。
高板本指的是 6以上
低版本值得是6以下 具體的 你自己去試 看場景。
我試了10幾個版本發現的這個問題
高版本 mysql 流傳遞進去的時候 少東西。所以一直不行。
因為用的人太少,所以官方一直也沒發現。也沒修復。。。
網上能查到的大部分資料 用的基本都是5版本的。
高版本他絕對用不了,不信你試試 哈哈。
本篇文章沒有那么多的代碼,只是記錄一下操作后的 的心得。和優化的整體思路,如果想要具體操作 還需要你有一定的功底,並且 可以根據相關的優化點,自己去查查咋實現。
因為加上代碼的話,就太多了。相信我 效率絕對杠杠的。