1.mongodb 表名和字段名統一用小寫字母
mongodb 是默認區分大小寫的,爲了不之前在 mysql 下遇到的大小寫敏感致使程序訪問頻頻出錯,
創建規範,mongodb 的表名和字段名都用小寫字母命名。
2.儘量的縮短字段名的長度
mongodb 的 schema free 致使了每筆數據都要存儲它的 key 以及屬性,這致使了這些數據的大量冗餘。
開發人員也許考慮到,從易讀性出發設計的 key 名,基本都是按照字面意思去設計的,這致使 key 很長,對應的數據存儲佔用了很大的空間。
因此,在你的程序裏維護一套字典便可,儘量下降 key 的長度。
譬如:
static final String CONTENT = "content";
static final String CONTENT_TYPE = "ctype";
static final String CONTENT_LENGTH = "clen";
3.記住,mongodb 的查詢每次只能用到一個索引
對於較複雜的表結構,可能會致使你頻頻使用聯合索引。
但記住:
1)mongodb 單表最大索引數爲 64 。
2)索引越多,插入或修改記錄就會致使 mongodb 越慢。寫鎖會阻塞讀請求,寫得越慢,阻塞讀請求越多、阻塞時間越長。
因此,
索引越加越多的時候,你可能須要審視一下表結構設計的合理性。
4.客戶端鏈接數大小的設置
mongodb-java-driver 的鏈接池,目前從觀察到的狀況是應用一開啓便根據 connectionsPerHost 變量的設置,創建所有鏈接,而後提供給程序使用,而且一旦其中某個鏈接到數據庫的訪問失敗,則會清空整個鏈接池到這臺數據庫的鏈接,並從新創建鏈接。
而 mongodb 對中斷鏈接的垃圾清理工做則是懶惰的被動清理方式,若是驅動程序端配置的鏈接數過大,一旦發生重連,則會致使 mongo 服務器端堆積大量的垃圾鏈接以及對應數據,致使主機資源耗盡。
建議: mongodb 驅動的鏈接池大小的設置通常應該控制 100 左右。
5.實例分離
mongodb 對數據庫的訪問所有加鎖。
如是查詢請求則設置共享鎖。
數據修改請求則設置全局排他鎖,且是實例級別的排他鎖。
寫鎖會阻塞讀請求,若是長時間持有寫鎖,會阻塞整個實例的讀請求。
建議:
1)
不一樣應用不該該共用同一個實例,防止互相阻塞!
2)如服務器資源不足,共用同一個實例,
要保證讀寫特性相同,如都是讀多寫少,防止一臺寫多應用阻塞讀請求。
(評語:舊版本的MongoDB (pre 2.0)擁有一個全局的寫入鎖,這個問題在2.0版本中的獲得了顯著的改善,而且在當前2.2版本中獲得了進一步的增強。MongoDB 2.2使用
數據庫級別的鎖在這個問題上邁進了一大步。
因此用 MongoDB 2.2的人能夠忽略此條目。)
6.須要重點關注的 mongodb 性能指標
關注主要性能指標:
1)Faults:顯示 mongodb 每秒頁面故障的數量,這個是 mongodb 映射到虛擬地址空間,而不是物理內存。這個值若是飆高的話,可能意味着機器沒有足夠的內存來存儲數據和索引。
2)Flushes:每秒作了多少次 fsync,顯示多少次數據被刷新進了磁盤。
3)locked:寫鎖。
4)idx miss:索引未命中比例。
5)qr | qw:讀寫鎖的請求隊列長度。
6)conn: 當前已經創建的鏈接數。
7.嚴重的空間碎片問題
mongodb 若是數據修改很頻繁,會出現比較嚴重的空間碎片問題,表如今磁盤文件擴張與實際數據量不相符,內存不夠用,索引命中率低,查詢效率下降。
碎片整理,目前咱們採用的版本沒有太有效的方法。
能夠用 db.repaireDatabase() 來整理數據庫,這個過程很是的慢。
若是是 master/slave 模式,則至關於執行一次主從切換,而後重新創建從庫。
若是是 replSet 架構,能夠停掉數據庫,而後刪除數據目錄,重新從複製組中全同步數據,這個時候要考慮 oplog 的尺寸。
一個大致的步驟:
1)先調用rs.freeze(1200),將每一個不想讓它成爲 primary 的機器讓它在 1200 秒內沒法成爲 primary(這步也能夠不作);
2)將 primary stepDown,不出意外新的 primary 會起來;
3)將原 primary kill 掉;
4)刪掉全部 data 數據(調用 repair 很慢,真不如干掉從新來);
5)再重啓動原 primary 的進程;
6)以此循環完成整個複製組的所有重建。
8.鏈接池 WriterConcern 模式選擇
有些應用配置了 WriterConcern.SAFE 模式,即w=1;這種配置意味着客戶端在插入數據或更新數據的時候,要求 mongodb 必須將所更新的數據寫入磁盤並返回更新成功的信息給程序。
若是碰上應用程序訪問壓力大,mongodb 就會反應遲鈍,並可能會假死。
針對此狀況,須要評估數據的一致性需求,作出合適調整。
咱們通常建議關閉此選項。
(評語:劉奎波的業務中心優化時就關閉了這個 WriterConcern.SAFE 模式)
9.開發時注意的細節
1)
更新某條數據的時候,先查出來再更新會減少鎖的時間;
2)只有真正須要的字段才select出來;
3)
只有返回不多結果的查詢才用索引,不然會加載太多數據,比沒有用索引還慢!
4)屬性比較多的時候,創建分層的關係可以提升查詢效率,不然每一個記錄都要過一遍才能找到要的屬性。
(評語:貌似說的是以
Array
形式存儲的
subdocument
)
5)skip+limit 翻頁,越日後面越慢。比較靠譜的作法是,先找出上次的id,翻頁的時候不用 skip:
last_row_id = ObjectId('....');
db.activity_stream->find({_id:{$lt: last_row_id },user_id:20 } ).sort( {_id:-1} ).limit(10); php
10.關於硬件資源的選擇
虛擬機能夠很好的隔離資源,並可動態的擴展。
咱們建議 mongodb 的部署採用虛擬機的方式,每一個虛擬機部署一個實例,使各節點分散在不一樣的物理機上,根據應用的前期預測,平衡虛擬機的之間的i/o。
參考資源:
贈圖2枚: