前言
MongoDB是非關係型數據庫的典型表明,DB-Engines Ranking 數據顯示,近年來,MongoDB在 NoSQL領域一直獨佔鰲頭。MongoDB是爲快速開發互聯網應用 而設計的數據庫系統,其數據模型和持 久化策略就是爲了構建高讀/寫的性能,而且能夠方面的彈性拓展。隨着MongoDB的普及和使用量的快 速增加,爲了規範使用,便於管理和獲取更高的性能,整理此文檔。咱們從 數據庫設計規範、集合設計 規範、索引設計規範、文檔設計規範、API使用規範、鏈接規範等方面進行闡述和要求。mysql
存儲選型
- 主要解決大量數據的訪問效率問題, 減小mysql 壓力。MongoDB內建了多種數據分片的特性,可 以很好的適應大數據量的需求。內建的Sharding分片特性避免系統在數據增加的過程當中遇到性能 瓶頸。
- 複雜數據結構,以多種不一樣查詢條件去查詢同一份數據。MongoDB的BSON數據格式很是適合文 檔化格式的存儲及查詢;支持豐富的查詢表達式,可輕易查詢文檔中內嵌的對象和數組及子文檔。
- 非事務而且關聯性集合不強的均可以使用(MongoDB4.0+支持跨Collection事務,MongoDB4.2+支持跨Shard事務)
- 無多文檔事務性需求及複雜關聯檢索
- 業務快速迭代,需求頻繁變更業務
- 數據模型不固定,存儲格式靈活場景
- 單集羣讀寫併發過大沒法支撐業務增加
- 指望 5 個 9 的數據庫高可用場景
更多關注微信公衆號"SpringForAll社區"
1、庫設計規範
- 【強制】數據庫命名規範:db_xxxx
-
【強制】庫名所有小寫,禁止使用任何_
之外的特殊字符,禁止使用數字打頭的庫名,如:123_abc
;算法
說明:庫以文件夾的形式存在,使用特殊字符或其它不規範的命名方式會致使命名混亂
- 【強制】數據庫名稱最多爲 64 個字符。
- 【強制】在建立新的庫前應儘可能評估該庫的體積、QPS等,提早與DBA討論是應該新建一個庫仍是專門爲該庫建立一個新的集羣;
2、集合設計規範
- 【強制】集合名所有小寫,禁止使用任何
_
之外的特殊字符,禁止使用數字打頭的集合名,如:123_abc
,禁止system打頭; system是系統集合前綴;
- 【強制】集合名稱最多爲64字符;
- 【建議】一個庫中寫入較大的集合會影響其它集合的讀寫性能,若是業務比較繁忙的集合在一個DB中,建議最多80個集合,同時也要考慮磁盤I/O的性能;
- 【建議】若是評估單集合數據量較大,能夠將一個大表拆分爲多個小表,而後將每個小表存放在獨立的庫中或者sharding分表;
- 【建議】MongoDB的集合擁有"自動清理過時數據"的功能,只需在該集合中文檔的時間字段增長一個TTL索引便可實現該功能,但須要注意的是該字段的類型則必須是mongoDate(),必定要結合實際業務設計是否須要;
-
【建議】設計輪詢集合---集合是否設計爲Capped限制集,必定要結合實際業務設計是否須要;sql
建立集合規則
不一樣的業務場景是可使用不一樣的配置;數據庫
db.createCollection("logs",
{ "storageEngine": { "wiredTiger":
{ "configString": "internal_page_max=16KB,
leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB"} }
})
-
- 若是是讀多寫少的表在建立時咱們能夠儘可能將 page size 設置的比較小 ,好比 16KB,若是表數據量不大
("internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB")
- 若是這個讀多寫少的表數據量比較大,能夠爲其設置一個壓縮算法,例如:
"block_compressor=zlib, internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB"
- 注意:該zlib壓縮算法不要使用,對cpu消耗特別大,若是使用snapp消耗20% cpu,並且使用zlib能消耗90%cpu,甚至100%
-
若是是寫多讀少的表,能夠將 leaf_page_max 設置到 1MB,並開啓壓縮算法,也能夠爲其制定操做系統層面 page cache 大小的 os_cache_max 值,讓它不會佔用太多的 page cache 內存,防止影響讀操做;數組
讀多寫少的表 internal_page_max=16KB 默認爲4KB leaf_page_max=16KB 默認爲32KB leaf_value_max=8KB 默認爲64MB os_cache_max=1GB 默認爲0 讀多寫少的表 並且數據量比較大 block_compressor=zlib 默認爲snappy internal_page_max=16KB 默認爲4KB leaf_page_max=16KB 默認爲32KB leaf_value_max=8KB 默認爲64M
3、文檔設計規範
- 【強制】集合中的 key 禁止使用任何 "_"(下劃線)之外的特殊字符。
- 【強制】儘可能將一樣類型的文檔存放在一個集合中,將不一樣類型的文檔分散在不一樣的集合中;相同類型的文檔可以大幅度提升索引利用率,若是文檔混雜存放則可能會出現查詢常常須要全表掃描的狀況;
- 【建議】禁止使用_id,如:向_id中寫入自定義內容;
說明:MongoDB的表與InnoDB類似,都是索引組織表,數據內容跟在主鍵後,而_id是MongoDB中的默認主鍵,一旦_id的值爲非自增,當數據量達到必定程度以後,每一次寫入均可能致使主鍵的二叉樹大幅度調整,這將是一個代價極大的寫入, 因此寫入就會隨着數據量的增大而降低,因此必定不要在_id中寫入自定義的內容。
- 【建議】儘可能不要讓數組字段成爲查詢條件;
- 【建議】若是字段較大,應儘可能壓縮存放;
不要存放太長的字符串,若是這個字段爲查詢條件,那麼確保該字段的值不超過1KB;MongoDB的索引僅支持1K之內的字段,若是你存入的數據長度超過1K,那麼它將沒法被索引
- 【建議】儘可能存放統一了大小寫後的數據 ;
- 【建議】若是評估單集合數據量較大,能夠將一個大表拆分爲多個小表,而後將每個小表存放在獨立的庫中或者sharding分表;
4、索引設計規範
- 【強制】MongoDB 的組合索引使用策略與 MySQL 一致,遵循"最左原則";
- 【強制】索引名稱長度不要超過 128 字符
- 【強制】應儘可能綜合評估查詢場景,經過評估儘量的將單列索引併入組合索引以下降因此數量,結合1,2點;
- 【建議】優先使用覆蓋索引
- 【建議】建立組合索引的時候,應評估索引中包含的字段,儘可能將數據基數大(惟一值多的數據)的字段放在組合索引的前面;
- 【建議】MongoDB 支持 TTL 索引,該索引可以按你的須要自動刪除XXX秒以前的數據並會盡可能選擇在業務低峯期執行刪除操做;看業務是否須要這一類型索引;
- 【建議】在數據量較大的時候,MongoDB 索引的建立是一個緩慢的過程,因此應當在上線前或數據量變得很大前儘可能評估,按需建立會用到的索引;
- 【建議】若是你存放的數據是地理位置信息,好比:經緯度數據。那麼能夠在該字段上添加 MongoDB 支持的地理索引:2d 及 2dsphere,但他們是不一樣的,混用會致使結果不許確;
5、API使用規範
- 【強制】在查詢條件的字段或者排序條件的字段上必須建立索引。
- 【強制】查詢結果只包含須要的字段,而不查詢全部字段。
- 【強制】在文檔級別更新是原子性的,這意味着一條更新 10 個文檔的語句可能在更新 3 個文檔後因爲某些緣由失敗。應用程序必須根據本身的策略來處理這些失敗。
- 【建議】單個文檔的BSON size不能超過16M;
- 【建議】禁用不帶條件的update、remove或者find語句。
- 【建議】限定返回記錄條數,每次查詢結果不超過 2000 條。若是須要查詢 2000 條以上的數據,在代碼中使用多線程併發查詢。
- 【建議】在寫入數據的時候,若是你須要實現相似 MySQL 中 INSERT INTO ON DUPLICATE KEY UPDATE 的功能,那麼能夠選擇 upsert() 函數;
- 【建議】寫入大量數據的時候能夠選擇使用 batchInsert,但目前 MongoDB 每一次可以接受的最大消息長度爲48MB,若是超出48MB,將會被自動拆分爲多個48MB的消息;
- 【建議】索引中的-1和1是不同的,一個是逆序,一個是正序,應當根據本身的業務場景創建適合的索引排序,須要注意的是{a:1,b:-1} 和 {a:-1,b:1}是同樣的;
- 【建議】在開發業務的時候儘可能檢查本身的程序性能,可使用 explain() 函數檢查你的查詢執行詳情,另外 hint() 函數至關於 MySQL 中的 force index();
- 【建議】若是你結合體積大小/文檔數固定,那麼建議建立 capped(封頂)集合,這種集合的寫入性能很是高並沒有需專門清理老舊數據,須要注意的是 capped 表不支持remove() 和 update()操做;
- 【建議】查詢中的某些 操做符可能會致使性能低下,如ne,,exists,,or,儘可能在業務中不要使用;
:由於鬆散的文檔結構致使查詢必須遍歷每個文檔
ne:若是當取反的值爲大多數,則會掃描整個索引微信
:可能會致使查詢優化器不知道應當使用哪一個索引,因此會常常退化爲全表掃描數據結構
nin:全表掃描多線程
:有多少個條件就會查詢多少次,最後合併結果集,因此儘量的使用併發
inapp
- 【建議】不要一次取出太多的數據進行排序,MongoDB 目前支持對32MB之內的結果集進行排序,若是須要排序,那麼請儘可能限制結果集中的數據量;
- 【建議】MongoDB 的聚合框架很是好用,可以經過簡單的語法實現複雜的統計查詢,而且性能也不錯;
- 【建議】若是須要清理掉一個集合中的全部數據,那麼 remove() 的性能是很是低下的,該場景下應當使用 drop();remove() 是逐行操做,因此在刪除大量數據的時候性能不好;
- 【建議】在使用數組字段作爲查詢條件的時候,將與覆蓋索引無緣;這是由於數組是保存在索引中的,即使將數組字段從須要返回的字段中剔除,這樣的索引仍然沒法覆蓋查詢;
- 【建議】在查詢中若是有範圍條件,那麼儘可能和定值條件放在一塊兒進行過濾,並在建立索引的時候將定值查詢字段放在範圍查詢字段前;
6、鏈接規範
- 【強制】正確鏈接副本集,副本集提供了數據的保護、高可用和災難恢復的機制。若是主節點宕 機,其中一個從節點會自動提高爲從節點。
- 【建議】合理控制鏈接池的大小,限制鏈接數資源,可經過Connection String URL中的 maxPoolSize 參數來配置鏈接池大小。
- 【建議】複製集讀選項 默認狀況下,複製集的全部讀請求都發到Primary,Driver可經過設置的Read Preference 來將 讀請求路由到其餘的節點。
本文由博客一文多發平臺
OpenWrite 發佈!