1、$where查询
不是非常必要时,一定要避免使用“$where”查询,因为它们在速度上要比常规查询慢很多。每个文档要从BSON转换成Javascript对象,然后通过“$where”的表达式来运行。同样还不能利用索引。所以,只在走投无路时才考虑“$where”这种用法。
将常规查询作为前置过滤,与“$where”组合使用可以不牺牲性能。如果可能的话,用索引根据非“$where”子句进行过滤,“$where”只用于对结果进行调优。
2、游标
数据库使用游标来返回find的执行结果,客户端对游标的实现通常能够对最终结果进行有效的控制。可以限制结果的数量,略过部分结果,根据任意方向任意键的组合对结果进行各种排序,或者是执行其他一些功能强大的操作。
要想从shell中创建一个游标,首先要对集合填充一些文档,然后对其执行查询,并将结果分配给一个局部变量(用var声明的变量就是局部变量)。要迭代结果,可以使用游标的next方法,也可以使用hasNext来查看有没有其他结果。例如:
> 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}) #索引内嵌文档中的键和普通的键创建索引没有什么区别
db.people.ensureIndex({"username":1},{"background":true}) #建立索引既耗时也费力,还需要消耗很多资源。使用{"background":true}选项可以使这个过程在后台完成,同时正常处理请求
建立索引时要考虑如下问题:
- 会做什么样的查询?其中哪些键需要索引?
- 每个键的索引方向是怎样的?
- 如何应对扩展?有没有种不同的键的排列可以使常用数据更多地保留在内存中?
要是能回答这些问题,说明你已经做好了索引的准备了。
创建索引的缺点就是每次插入、更新和删除时都会产生额外的开销。这是因为数据库不但需要执行这些操作,还要将这些操作在集合的索引中标记。因此,要尽可能少创建索引。每个集合默认的最大索引个数为64个。
注意:一定不要索引每一个键。这会导致插入非常慢,还会占用很多空间,并且很可能对查询速度提升不大。
MongoDB排序需要将所有数据提取到内存来排序,因此,可以做无索引排序是有个上限的,那就是不可能在内存里面做T级别数据的排序。一旦集合大到不能在内存中排序,MongoDB就会报错。
索引管理:索引的元信息存储在每个数据库的system.indexes集合中。这是一个保留集合,不能对其插入或者删除文档。操作只能通过ensureIndex或者dropIndexes进行。
建立索引既耗时也费力,还需要消耗很多资源。使用{"background":true}选项可以使这个过程在后台完成,同时正常处理请求。
MongoDB支持动态建立普通集合,还支持固定集合(要实现创建,而且大小固定。如果固定集合空间不足,最早的文档就会被删除,为新的文档腾出空间,这意味着固定集合在新文档插入的时候自动淘汰最早的文档。)
固定集合和普通集合还有一个区别,就是在默认情况下固定集合没有索引,即便是“_id”上也没有索引。
固定集合有种特殊的排序方式,叫做“自然排序”。自然排序就是文档在磁盘上的顺序顺时针方向依次的。文档总数安装插入的顺序存储的,自然顺序就是与此相同的。也可以使用自然排序按照反向插入的顺序查询。
尾部游标只能在固定集合上使用。