1帖烘、$where查詢
不是非常必要時洒试,一定要避免使用“$where”查詢,因為它們在速度上要比常規(guī)查詢慢很多秘遏。每個文檔要從BSON轉(zhuǎn)換成Javascript對象拷沸,然后通過“$where”的表達式來運行限匣。同樣還不能利用索引余指。所以,只在走投無路時才考慮“$where”這種用法舍扰。
將常規(guī)查詢作為前置過濾,與“$where”組合使用可以不犧牲性能希坚。如果可能的話边苹,用索引根據(jù)非“$where”子句進行過濾,“$where”只用于對結(jié)果進行調(diào)優(yōu)裁僧。
2个束、游標
數(shù)據(jù)庫使用游標來返回find的執(zhí)行結(jié)果,客戶端對游標的實現(xiàn)通常能夠?qū)ψ罱K結(jié)果進行有效的控制聊疲〔绲祝可以限制結(jié)果的數(shù)量,略過部分結(jié)果获洲,根據(jù)任意方向任意鍵的組合對結(jié)果進行各種排序阱表,或者是執(zhí)行其他一些功能強大的操作。
要想從shell中創(chuàng)建一個游標,首先要對集合填充一些文檔最爬,然后對其執(zhí)行查詢涉馁,并將結(jié)果分配給一個局部變量(用var聲明的變量就是局部變量)。要迭代結(jié)果爱致,可以使用游標的next方法烤送,也可以使用hasNext來查看有沒有其他結(jié)果。例如:
> var cursor = db.collection.find();
> while (cursor.hasNext()){
obj = cursor.next();
// do stuff
}
3糠悯、索引
建立索引的方法:
db.people.ensureIndex({"username":1}) #以username為索引
db.people.ensureIndex({"date":1,"username":1}) #以date,username為索引
db.people.ensureIndex({"comments.date":1}) #索引內(nèi)嵌文檔中的鍵和普通的鍵創(chuàng)建索引沒有什么區(qū)別
db.people.ensureIndex({"username":1},{"background":true}) #建立索引既耗時也費力帮坚,還需要消耗很多資源。使用{"background":true}選項可以使這個過程在后臺完成逢防,同時正常處理請求
建立索引時要考慮如下問題:
- 會做什么樣的查詢叶沛?其中哪些鍵需要索引?
- 每個鍵的索引方向是怎樣的忘朝?
- 如何應對擴展灰署?有沒有種不同的鍵的排列可以使常用數(shù)據(jù)更多地保留在內(nèi)存中?
要是能回答這些問題局嘁,說明你已經(jīng)做好了索引的準備了溉箕。
創(chuàng)建索引的缺點就是每次插入、更新和刪除時都會產(chǎn)生額外的開銷悦昵。這是因為數(shù)據(jù)庫不但需要執(zhí)行這些操作肴茄,還要將這些操作在集合的索引中標記。因此但指,要盡可能少創(chuàng)建索引寡痰。每個集合默認的最大索引個數(shù)為64個。
注意:一定不要索引每一個鍵棋凳。這會導致插入非常慢拦坠,還會占用很多空間,并且很可能對查詢速度提升不大剩岳。
MongoDB排序需要將所有數(shù)據(jù)提取到內(nèi)存來排序贞滨,因此,可以做無索引排序是有個上限的拍棕,那就是不可能在內(nèi)存里面做T級別數(shù)據(jù)的排序晓铆。一旦集合大到不能在內(nèi)存中排序,MongoDB就會報錯绰播。
索引管理:索引的元信息存儲在每個數(shù)據(jù)庫的system.indexes集合中骄噪。這是一個保留集合,不能對其插入或者刪除文檔蠢箩。操作只能通過ensureIndex或者dropIndexes進行腰池。
建立索引既耗時也費力尾组,還需要消耗很多資源。使用{"background":true}選項可以使這個過程在后臺完成示弓,同時正常處理請求讳侨。
MongoDB支持動態(tài)建立普通集合,還支持固定集合(要實現(xiàn)創(chuàng)建奏属,而且大小固定跨跨。如果固定集合空間不足,最早的文檔就會被刪除囱皿,為新的文檔騰出空間勇婴,這意味著固定集合在新文檔插入的時候自動淘汰最早的文檔。)
固定集合和普通集合還有一個區(qū)別嘱腥,就是在默認情況下固定集合沒有索引耕渴,即便是“_id”上也沒有索引。
固定集合有種特殊的排序方式齿兔,叫做“自然排序”橱脸。自然排序就是文檔在磁盤上的順序順時針方向依次的。文檔總數(shù)安裝插入的順序存儲的分苇,自然順序就是與此相同的添诉。也可以使用自然排序按照反向插入的順序查詢。
尾部游標只能在固定集合上使用医寿。