各个数据库存二进制大文件的性能测试
1前言
? 有個項目軟件前端將二進制大文件存在了indexDB,每次給后端傳文件(需要傳到底層C++進行調用)都會導致內存占用飆升,想著使用前后端都能共同操作的數據庫來解決這個內存占用的問題,并且希望這個更具盡可能的輕量,可以嵌入到程序中是最好的,通過一個安裝包進行安裝。
2各個數據庫的性能比較
2.1 MySQL
? 預先準備35MB的Byte數組數據,將其存到數據庫的格式為blob,測試MySQL存儲100塊35MB的數據需要300秒,平均一塊需要3s時間。
2.2 MongoDB
? MongoDB的數據是采用鍵值對的形式進行存儲,一樣是采用100塊35MB的數據進行寫入,測試需要45s時間,平均一塊是450ms。
2.3 SQLite測試及優化過程
2.3.1 概述
? SQLite使用Mybatis作為ORM框架進行100塊35MB的寫入速度,100塊使用了12s,平均一塊35MB寫入速度是120ms,遠快于前面兩種使用Mybatis讀數據庫blob格式出現不支持的問題,將ORM換到JdbcTemplate后,支持blob格式,進行讀,一塊35MB讀了40s時間,猜測是JdbcTemplate是比較落后的方案,沒有針對大文件優化。
2.3.2 優化流程
(一)表結構優化
? 主鍵id改為PrimaryKey,并且設置自增,使得每次都可以B+樹主鍵索引命中查詢內容。
(二)Mybatis優化
依然是換回springboot最主流的mybatis框架,手寫mapper.xml文件處理blob格式,指定handler處理器編寫對blob的處理,最終實現對blob的讀取。優化后,對讀取的數據不進行解析的話,平均一塊35MB的數據讀取50ms,涉及到數據解析(需要用byte數組接blob,并對整個數組中的數據解析取值)會再多一些時間。
(三)使用JPA
? Mybatis除了對blob數據讀取支持不好外,操作sqlite數據庫時,使用自增id無法正常生成id的值,決定換到JPA進行嘗試。
在JPA下,寫100塊35MB的數據如下:
?
? 可見寫入速度接近于Mybatis和JdbcTemplate,都是100+ms。
? 測試讀100塊35MB的數據:
? 讀的速度得到很大提升,30ms左右,快于mybatis下的50ms。
? 在測試35塊100MB大小的數據的寫操作:
? 寫操作的時間基本成線性增長,100MB一塊寫入需要400ms+。
? 再測試讀操作:
100MB的讀操作性能還是很高,讀一塊100MB大小的分塊是100+ms。(上述測試涉及到的讀操作都是沒有對數據進行解析的)
(四)針對寫過程進行優化
? 當前場景下,需要不斷對數據庫執行多個插入操作,默認情況下,每次插入一個數據都會開始事務和提交事務,多次提交會重復這個流程,磁盤I/O頻率高,嘗試開啟事務,在數據都準備好情況下再進行提交事務。在插入的方法上加入注解@Transactional,下面測試有無@Transactional情況下存10個100MB數據的情況。
左邊是使用了注解后的結果,右邊是沒有,開啟事務后提升是很明顯的。一塊100MB的分塊寫入從400ms降低到300ms,但會導致另外一個問題,如果35個100MB的數據同時存進去會出現java堆溢出,因為這3.5g在事務commit前都是放在內存里面導致溢出。
(五)針對讀過程嘗試進行優化
? 對讀過程嘗試調節了SQLite一些參數,但是基本沒有提升。
設置PRAGMA synchronous = OFF,關閉寫同步,PRAGMA synchronous = OFF,在 sqlite3 中 synchronous 有三種模式,分別是 FULL,NORMAL 和 OFF,在系統意外終止的時候,安全性逐級減弱,FULL模式下,保證數據不會損壞,安全性最高,寫入速度也最慢。
設置PRAGMA page_size = 8192,通過設置PAGE_SIZE參數,調整最小存儲單元PAGE的大小,由于存入的數據較大,嘗試改成8192,甚至16384。
設置完沒有提升,猜測上面參數是針對數量條數很大的情況才有提升,當前情況是數據條數不多,但單獨的每條數據占用內存大。
2.4 LevelDB
? Leveldb也是輕量級數據庫,屬于NOSQL,是以key-value形式進行存儲,Java和node.js都能同時使用,但是經過測試,同樣存入35個100MB分塊大小的數據,每一塊存入時間是400ms,每一塊讀取時間也接近400ms,相比較jpa下的sqlite表現,并沒有提升。
2.5 IndexDB(原有方案)
? 讀100MB的分塊是50毫秒,讀性能非常的好。
寫入100MB分塊的時候,算上json轉blob 以及入庫的時間,大概是100-200ms,時間遠短于尚未做數據處理的sqlite(事務下300-400ms)。
3 結論
上述所測試的數據庫性能都不如原有方案下的indexDB,最接近indexDB的sqlite,讀寫性能數據比較如下:
100MB分塊的寫入,包括json數據解析,indexDB是100-200ms,sqlite不包括數據解析在開啟事務的情況下是300-400ms,不開啟事務則是400-500ms。
100MB分塊的讀取,不包括數據解析:indexDB是50ms,sqlite是100-200ms。
總結
以上是生活随笔為你收集整理的各个数据库存二进制大文件的性能测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java监听全局组合键
- 下一篇: 怎么破?韩国竟举办多场宣讲强调日本福岛核