mongodb如何写入图片_CTO之瞳-数据库-MongoDB
MongoDB,常用的NoSql數據庫,在https://db-engines.com/en/ranking 里被分類為文檔型數據庫。
?
本文從以下五個方面來了解MongoDB (和上一篇一樣,基礎操作請查詢官方文檔或者菜鳥教程)
1.使用場景
一個業務系統的搭建,什么情況下用關系型數據庫MySql,又在什么情況下用文檔型數據庫MongoDB呢?
在回答這個問題之前,先來了解一下MongoDB與關系型數據庫的幾個顯著區別。在MongoDB的自述中,抽取出個人認為重要的兩個點:
https://www.mongodb.com/nosql-explained
1. Dynamic Schemas:動態的數據結構
MySql需要先定義好一張表的字段,然后每個字段的值才能被插入;MongoDB不用預先定義字段和數據類型,可以隨時動態插入新增的字段。對于一個不斷變化發展的業務,數據定義也必然是變化發展的,因此一個靈活可變的數據結構才能較好的應對。比如,社交類軟件,每一次的改版,后臺的數據結構都有相應的變化。
2. Auto-sharding:自動分片
數據庫層面原生的水平分庫分表方案,對于海量數據,不用人為的去做分庫分表操作。基本原理如下圖所示(圖片來自MongoDB官網)。
基于以上兩個特點,不難看出在什么情況下需要使用MongoDB。
- 遇到經常變化的數據需求。產品今天提需求要支持每個用戶設定3個興趣愛好;明天起床覺得3這個數貌似不是自己的幸運數字啊,還是改為7個興趣愛好吧;后天老板說我有8個愛好怎么辦,產品又默默的改了需求。如果用MySql來存儲,相信DBA會默默的準備麻袋和棍棒。所以,一般不經常變的個人數據存在MySql里,例如生日、姓名、籍貫,當然還有性別。而經常變化的數據通過userid關聯到MongoDB里存儲,比如頭像、自我介紹、興趣愛好,可能、也許、應該還有婚姻狀況。
- 海量數據,例如日志。
其實MongoDB的使用場景,在官網的用戶案例里已經給出了很多答案:
百度在什么場景用MongoDB?信息,圖片分享,百度云,百度地圖,社交論壇,用戶行為日志。
奇虎呢?基于地理位置信息的移動搜索與結果分發,單點登錄信息的緩存(The user’s SSO session is cached in MongoDB for ultra-fast access. MongoDB supports millions of concurrent users, handling 30,000 operations per second and 1.8 billion queries daily. 關于性能在本篇第3部分中闡述),日志分析平臺。
還有很多其他公司的應用實例,大家可以訪問下面這個鏈接獲取信息。
https://www.mongodb.com/mongodb-scale
最常用的幾個場景還是:文檔,LBS相關的地理位置信息,日志。這幾個場景的共同特點:數據量大,需要經常查詢。
2.存儲引擎
MongoDB 4.x版本有兩個常用的存儲引擎(關于存儲引擎的概念,請參看上一篇文章 CTO之瞳-數據庫-MySql)
1. WiredTiger:默認引擎,也是社區版(免費版)唯一支持的引擎。
從下圖(圖片來自MongoDB官網)可以看出,WT引擎在內存中分了兩個緩存區域,一個是沒做數據壓縮的WT Cache,另一個是做了數據壓縮的FS Cache,查詢的順序是先去WT Cache,沒有命中再去FS Cache,最后再去磁盤;而存進磁盤的數據都是壓縮過的(默認壓縮)。
2. In-Memory:企業版才支持的引擎
看名字就想象的出,所有的數據是存在內存中的,目的是為了避免硬盤I/O操作,提升性能。缺點也很明顯,一旦關機或重啟,所有數據都會丟失。看到這里,始終想不明白In-Memory引擎的用途,直到看見了MongoDB的又一特性Replication(復制)才秒懂。
Replication類似于MySql Router機制。試想一下,如果把Master設為In-Memory模式,而數據持久化到Slave上,讀寫不經過硬盤,性能是何其的強勁;或者把一臺slave設為高頻數據的專用讀取源,比如用戶token,這個訪問性能也一定是杠杠的。猜想第1節里奇虎案例提到的性能參數 (MongoDB supports millions of concurrent users, handling 30,000 operations per second and 1.8 billion queries daily),就是通過使用In-Memory引擎實現的。
對于In-Memory引擎的使用場景,在第5節-分片與復制里再詳述。
3.性能測試
測試環境:
MongoDB 4.2, Windwos社區版, WT engine
IDEA 2019
Windows10
i7-9700F, 8G內存, 東芝固態硬盤
代碼訪問路徑:
https://gitlab.com/ctoeyes/mongodb
Database:test
Collection:WiredTiger
為了和上一篇MySql的測試結果比對,MongoDB的數據表設計如下
實驗一:單線程連續插入5w條數據,數據和MySql測試案例保持一致。
實驗二:單線程連續查詢1w次,每次以_id列作為查詢條件(索引查詢)。
實驗三:單線程連續查詢1w次,每次以D列作為查詢條件(非索引查詢)。
實驗四:查看數據占用空間大小。
實驗結果如下:
和上一篇MySql的結果比對如下:
插入速度:MongoDB 4.2支持事務,與同樣支持事務處理的MySql-InnoDB比較,性能是較優的。
索引列查詢速度:MongoDB劣于MySql的兩個引擎,這可能與MongoDB的索引采用B樹的數據結構,而MySql索引采用B+樹數據結構有關,詳細的在下一節“索引-B樹”里討論。
非索引列查詢速度,MongoDB也明顯慢于MySql,原因是否和MongoDB的數據默認壓縮后再存進磁盤有關?查詢前要解壓縮,有一定耗時。
占用空間:MongoDB占優。
4.索引-B樹
MongoDB索引采用的數據結構是B樹,以上一篇MySql里相同的數據表為例,畫一下在MongoDB里的數據結構。
這些數據長成這樣:
回顧上一篇MySql InnoDB引擎的B+樹
可以發現兩者有兩個很明顯的區別
1. B+樹只有最下層的葉子節點保存數據,其他節點只保存關鍵字;而B樹每一層節點均保存數據。因此單一數據查詢,B+樹必須查到最下一層,而B樹只有在最壞情況下需要查詢到最下層。但第3節的實驗結果明明索引查詢是MySql的B+樹勝出,為什么?個人猜測(未必正確),因為B+樹的非葉節點不保存數據,空間占用小而被緩存在內存中,這樣訪問速度快;B樹的非葉節點因為保存數據,空間占用大,有些存在磁盤里,因而訪問速度慢。
2. B+樹每個相鄰的葉子節點有指針連接,而B樹沒有。因此范圍查詢,B+樹更有優勢。
思考:如果把Seat No也設為索引,數據應該長什么樣(此時B+樹只有葉子節點保存數據的優勢就體現出來了)?
5.分片與復制
分片(Sharding)與復制(Replication)是MonoDB的兩種擴展方式,前文也提到過。
分片:實質是一種水平方向上的分庫分表,主要目的是為了增大容量、提升性能。第1節里的示意圖一目了然,不再重復。
復制:類似于MySql Router,主要目的是數據備份、故障熱切換、讀寫分離。而第2節里提到的In-Memory引擎用在復制模式里,也可以幫助提升性能,看下圖(圖片來自MongoDB官網)。
如果把右邊的secondary DB設為讀操作的默認DB,同時設定它使用In-Memory引擎,那么一些常用的數據讀取會極大的提速。當然,這種情況下,需要保證最少兩臺secondary。為什么呢?試想如果只有一臺secondary且是In-Memory模式,此時primary掛了,secondary自動接替為primary,然后它也宕機了,那么primary切換后寫入的數據就會全部丟失。這時咋辦?趕緊回家卷鋪蓋跑路吧 ^^
如果把primary設為In-Memory模式,讀寫都通過primary,而數據持久化到secondary中,那么讀寫性能都可以得到極大的提升。
了解了分片與復制機制后,想到一個問題,這兩種方式能不能放到一起用?也就是既要分表擴容,又要數據備份與故障熱切換。仔細看了下MondoDB的官網,其實已經給出了答案,看下圖(圖片來自MongoDB官網)。
在介紹Sharding架構的圖中,已經明確標明了(紅色圈圈),每一臺Shard DB和Config Server都可以是一組Replica集群。
所以
- 對于小型業務,一臺Primary+一臺Secondary的Replication方式即可滿足業務需求。
- 對于中大型業務,采用Sharding + Replication的矩陣組合基本也可滿足業務需求。
MongoDB就聊到這里,依然是九牛一毛,關鍵是思考;另外,官方文檔仔細看,有很多有價值的信息可以挖掘。
下一篇開始說說后端體系,坑中坑,頭大,現在覺得B坑的一年之約太樂觀了。
總結
以上是生活随笔為你收集整理的mongodb如何写入图片_CTO之瞳-数据库-MongoDB的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: g++ 安装python_以后再也不用“
- 下一篇: mysql 聚簇索引和非聚簇索引_MyS