您好,登錄后才能下訂單哦!
一.命名規(guī)則
1.mongodb版本選擇:
默認新裝數(shù)據(jù)庫使用MongoDB 3.X 社區(qū)版。建議3.2.10+
2.數(shù)據(jù)庫設(shè)計規(guī)范
數(shù)據(jù)庫名可以是滿足以下條件的任意UTF-8字符串:
(1)不能出現(xiàn)除“_”字符以外的特殊字符;
(2)不能含有”(空格)、.、$、/、、和(空字符);
(3)應(yīng)全部小寫;
(4)最多30字符。
(5)禁止使用數(shù)字打頭的庫名
3.集合命名規(guī)則
必須滿足下列條件的任意UTF-8字符串
(1)集合名不能是空字符串“”; 不能出現(xiàn)除“_”字符以外的特殊字符,禁止使用數(shù)字開頭的名稱;
(2)集合名不能以“system.”開頭,這是為系統(tǒng)集合保留的前綴。例如system.users這個集合保存著數(shù)據(jù)庫的用戶信息,system.namespaces集合保存著所有數(shù)據(jù)庫集合的信息;
(3)用戶創(chuàng)建的集合名字不能含有保留字符$。除非你要訪問系統(tǒng)創(chuàng)建的集合,否則不可在名字里出現(xiàn)$;
(4)集合名應(yīng)簡潔明了,盡量都使用小寫;
4.字段命名規(guī)范
(1)字段不能含有(空字符)。
(2)禁止使用數(shù)字開頭的字段名;
(3)不可以“”開頭命名字段名稱,不能出現(xiàn)除“”字符以外的特殊字符;
(4)字段引用必須采用集合名+被引用字段名稱。例如集合user的鍵id在集合user_info中被引用,用user_id作為鍵名;
(5)只有在遇到引用情況下,字段中包含的集合名首字母需要大寫,其他一律小寫格式。
(6)如果字段較大,應(yīng)盡量壓縮存放
(7)如果字段較大且會成為查詢條件,例如一長串的url,可以轉(zhuǎn)成md5后存放
(8)禁止自定義_id的值。
二:數(shù)據(jù)庫設(shè)計規(guī)范
1.
(1) 合理容量規(guī)劃和庫級拆分
創(chuàng)建新的數(shù)據(jù)庫時,提前進行容量規(guī)劃庫的集合數(shù),存儲容量,QPS等, 是放在已有集群,還是新創(chuàng) 建集群部署。
(2) 避免把所有集合都放在同一個數(shù)據(jù)庫,造成一個庫中集合過多;
(3) 業(yè)務(wù)禁止使用id字段;
業(yè)務(wù)避免向id字段寫入自定義的業(yè)務(wù)數(shù)據(jù):因MongoDB的 Jd字段默認是主鍵, 類似于MySQL InnoDB表的主鍵,如果業(yè)務(wù)寫入無序數(shù)據(jù)(如uuid/md5),集合本身是B+ Tree,為保證樹的平衡,會大副度調(diào)整內(nèi)部存儲數(shù)據(jù)結(jié)構(gòu);寫入數(shù)據(jù)的代價很大,容易導致寫入性能低;
(4) MongoDB數(shù)據(jù)是大小寫敏感的,如業(yè)務(wù)不區(qū)分大小,建議冗余一個全部大寫或小寫字段,用于不區(qū)分大小寫的數(shù)據(jù)檢索效率*
mongo中數(shù)據(jù)查詢是大小寫敏感的,例如{f,"aA"}的查詢條件, 不能匹配字段為“aa”,“AA", “Aa” 值的文檔。有的業(yè)務(wù)需忽略大小,需通過正則方式進行處理{f:aa/},雖實現(xiàn)忽略大小功能,但查詢效率很低,同時很耗CPU資源。 解決這類需求,希望冗余一個全大寫(或小寫)的字段,用于業(yè)務(wù)忽略大小的檢索需求。例如對f字段冗余tupper字 段,存儲字段內(nèi)容全大寫{f_upper."AA'}
(5) 對高頻大字段進行壓縮存儲:
很多高頻的查詢,如果存在返回較大字段數(shù)據(jù)(如10 KB以上),當QPS增加后很容易把MongoDB服務(wù)器網(wǎng)絡(luò)帶寬占滿。
或?qū)懭腩l次較高,會導數(shù)oplog實體很大。建議這類高頻和較大的數(shù)據(jù), 在業(yè)務(wù)層進行 壓縮后,再存入MongoDB中。
(6)ObjectId存儲時,作為ObjectId存儲,不可存成字符串類型;
原因:第一,方便查詢(字符串和ObjectId不能相互匹配)第二,ObjectId 含有有用的信息,如從插入的時間戳可以得知創(chuàng)建日期;第三,字符串表示的ObjectId要多占用兩倍的磁盤空間;
2.索引設(shè)計規(guī)范
(1)MongoDB的索引僅支持1K以內(nèi)的字段,如果你存入的數(shù)據(jù)長度超過1K,那么它將無法被索引
(2)索引名稱長度不要過長;命名方式:idx_字段名 ;組合索引建議包含所有字段名,過長的字段名可以采用縮寫形式。
(3)唯一索引命名規(guī)范:uniq_字段名稱
(3)應(yīng)盡量綜合評估查詢場景,通過評估盡可能的將單列索引并入組合索引以降低所以數(shù)量;
(4)索引越多,插入或修改記錄就會導致 mongodb 越慢。
(5)創(chuàng)建索引要在后臺創(chuàng)建,避免阻塞業(yè)務(wù)正常DML和查詢。db.works.createIndex({a:1,b:1},{"name":'idx_字段名'},{background:true})
(6)禁止在數(shù)組字段上創(chuàng)建索引;
(7)在創(chuàng)建組合索引的時候,應(yīng)評估索引中包含的字段,盡量將選擇性高(唯一值多的數(shù)據(jù))的字段放在組合索引的前面;
(8)在開發(fā)業(yè)務(wù)的時候盡量檢查自己的程序性能,多使用explain()查看執(zhí)行計劃;
(9)禁止冗余索引。 例如索引idx_account_sName_createTime {"account" : 1,"sName" : 1,"createTime" : -1}和索引idx_account {"account" : 1} 索引冗余,可刪除idx_account索引。
3.查詢規(guī)范
(1)查詢語句是否使用到索引,在查詢條件的鍵上,或者排序條件的鍵上必須有索引(數(shù)據(jù)量較小的集合除外);
(2)使用limit()限定返回結(jié)果集的大小,減少數(shù)據(jù)庫服務(wù)器的資源消耗,以及網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量。
(3)只查詢使用到的字段,而不查詢所有字段;盡量不要讓數(shù)組字段成為查詢條件
(4)執(zhí)行remove()刪除操作,未帶查詢條件,警告或報錯;
(5)查詢中的某些$操作符可能會導致性能低下,如 $ne,$not,$exists,$nin,$or,$where盡量在業(yè)務(wù)中不要使用
(6)MongoDB 的組合索引使用策略 遵循"最左原則",優(yōu)先使用覆蓋索引,查詢語句遵守復合索引字段順序
(7)必要時使用hint()強制使用某個索引查詢
(8)更新操作時,先查詢后更新,通過主鍵key更新,可以提高更新效率;
###應(yīng)用程序連接配置
合理設(shè)置讀寫分離,減少主節(jié)點壓力,提高可集群可擴展性
(1)mongo客戶端通過只讀偏好(read -preference)屬性設(shè)置,決定客戶端只讀查詢的路由規(guī)則。
(2)mongo客戶端默認所有查詢都路由到主節(jié)點查詢,而很多應(yīng)用程序只讀業(yè)務(wù)一-致性不高 (接受秒級別的同步延時), 可把只讀查詢路由到從節(jié)點。MongoDB正常 復制同步延時在1秒內(nèi)。
(3)如果業(yè)務(wù)只讀查詢,對數(shù)據(jù)- -致性要求不高(比如最壞情況按受60秒延時).建議程序drver的[只讀偏好]屬性設(shè)置為 secondaryPreferred.
mongo客戶端[只讀偏好]支持5種模式:
Read Preference Mode | Description |
---|---|
primary | 默認模式,客戶端所有只讀命令都發(fā)向主節(jié)點 |
primaryPreferred | 只讀查詢默認發(fā)給主節(jié)點,當主節(jié)點不可用時,轉(zhuǎn)發(fā)給從節(jié)點 |
secondary | 所有的只讀查詢發(fā)向從節(jié)點 |
secondaryPreferred | 所有只讀查詢發(fā)向從節(jié)點,如果所有從節(jié)點不可用時,轉(zhuǎn)發(fā)給主節(jié)點 |
nearest | 只讀查詢發(fā)給最近可用數(shù)據(jù)節(jié)點,不考慮節(jié)點的角色 |
1.分片鍵的幾個原則:
分片鍵是不可變。
分片鍵必須是索引。
分片鍵大小限制512bytes。
分片鍵用于路由查詢。
MongoDB不接受已進行collection級分片的collection上插入無分片鍵的文檔。
好的 shard key 應(yīng)該擁有如下特性:
1.key 分布足夠離散 (sufficient cardinality)
2.寫請求均勻分布 (evenly distributed write)
3.盡量避免 scatter-gather 查詢 (targeted read)
MongoDB的內(nèi)部機制保證了每個副本集(RS)包含了同樣數(shù)量的塊。
片鍵的選擇決定了三個重要的方面:
#####1. 讀和寫的分布
其中最重要的一點是讀和寫的分布。如果你總是朝一臺機器寫,那么這臺機器將會成為寫瓶頸,則你的集群的寫性能將會降低。這無關(guān)乎你的集群有多少個節(jié)點,因為所有的寫操作都只在一個地方進行。因此,你不應(yīng)該使用單調(diào)遞增的_id
或時間戳作為片鍵,這樣將會導致你一直往最后一個副本集中添加數(shù)據(jù)。
相類似的是如果你的讀操作一直都在同一個副本集上,那么你最好祈求你的任務(wù)能在機器內(nèi)存所能承受的范圍之內(nèi)。通過副本集將讀請求劃分開能夠使你的工作數(shù)據(jù)集大小隨著分片數(shù)線性擴展。這樣的話你能夠?qū)⒇撦d壓力均分到各臺機器的內(nèi)存和磁盤之上。
其次是數(shù)據(jù)塊的大小。MongoDB能夠?qū)⒋蟮臄?shù)據(jù)塊劃分成更小的,但這種情況僅僅在片鍵不同的情況下發(fā)生。如果你有巨量的數(shù)據(jù)文檔都使用了同樣的片鍵,那么你相應(yīng)的會得到巨大的數(shù)據(jù)塊。出現(xiàn)巨大塊是非常不好的,不僅僅因為它會導致數(shù)據(jù)的不平均分布,還因為一旦這個數(shù)據(jù)塊的大小超過某個值,那么你就不能夠在分片之間移動它了。
最后一點,如果能夠保證大部分的查詢請求都能夠命中盡可能少的分片那就最好了。對于一個查詢請求來說,其延遲直接取決于最慢的那個命中服務(wù)器的延遲;所以你命中的分片越少,那么理論上來說查詢將會越快。這一點并不是硬性的規(guī)定,不過如果能夠做到充分考慮那么應(yīng)該是很有利的。因為數(shù)據(jù)塊在分片上的分布僅僅是近似的遵循片鍵的順序,而并不是嚴格的強制指定。
讀和寫都能夠平均分布,并且它能夠保證每個文檔都有不同的片鍵所以數(shù)據(jù)塊能夠很精細。
對多個文檔的查詢必將命中所有的分片。
數(shù)據(jù)文件挪動小(優(yōu)勢)
因為數(shù)據(jù)文件遞增,所以會把insert的寫IO永久放在最后一片上,造成最后一片的寫熱點。同時,隨著最后一片的數(shù)據(jù)量增大,將不斷的發(fā)生遷移至之前的片上。
數(shù)據(jù)分布均勻,insert的寫IO均勻分布在多個片上。(優(yōu)勢)
對多個文檔的查詢必將命中所有的分片;大量的隨機IO,磁盤不堪重荷。
為防止巨大塊的產(chǎn)生,建議使用組合鍵,引入_id來細化。{keyname: 1, _id: 1}
原則就是:keyname可以是一個經(jīng)常被查詢的字段,盡可能基數(shù)較大;_id字段是有非常多不同的值可以供mongodb進行分割,這種策略適合大多業(yè)務(wù)情況;如果實在找不到keyname這樣字段,那么就對_id進行Hashed吧。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。