离线下载
PDF版 ePub版

geminiyellow · 更新于 2017-10-22 03:00:27

性能和工具

在这章中,我们来讲几个关于性能的话题,以及在 MongoDB 开发中用到的一些工具。我们不会深入其中的一个话题,不过我们会指出每个话题中最重要的方面。

索引(Index)

首先我们要介绍一个特殊的集合 system.indexes ,它保存了我们数据库中所有的索引信息。索引的作用在 MongoDB 中和关系型数据库基本一致: 帮助改善查询和排序的性能。创建索引用 ensureIndex :

// where "name" is the field name
db.unicorns.ensureIndex({name: 1});

删除索引用 dropIndex:

db.unicorns.dropIndex({name: 1});

可以创建唯一索引,这需要把第二个参数 unique 设置为 true:

db.unicorns.ensureIndex({name: 1},
    {unique: true});

索引可以内嵌到字段中 (再说一次,用点号) 和任何数组字段。我们可以这样创建复合索引:

db.unicorns.ensureIndex({name: 1,
    vampires: -1});

索引的顺序 (1 升序, -1 降序) 对单键索引不起任何影响,但它会在使用复合索引的时候有所不同,比如你用不止一个索引来进行排序的时候。

阅读 indexes page 获取更多关于索引的信息。

Explain

需要检查你的查询是否用到了索引,你可以通过 explain 方法:

db.unicorns.find().explain()

输出告诉我们,我们用的是 BasicCursor (意思是没索引), 12 个对象被扫描,用了多少时间,什么索引,如果有索引,还会有其他有用信息。

如果我们改变查询索引语句,查询一个有索引的字段,我们可以看到 BtreeCursor 作为索引被用到填充请求中去:

db.unicorns.find({name: 'Pilot'}).explain()

复制(Replication)

MongoDB 的复制在某些方面和关系型数据库的复制类似。所有的生产部署应该都是副本集,理想情况下,三个或者多个服务器都保持相同的数据。写操作被发送到单个服务器,也即主服务器,然后从它异步复制到所有的从服务器上。你可以控制是否允许从服务器上进行读操作,这可以让一些特定的查询从主服务器中分离出来,当然,存在读取到旧数据的风险。如果主服务器异常关闭,从服务中的一个将会自动晋升为新的主服务器继续工作。另外,MongoDB 的复制不在本书的讨论范围之内。

分片(Sharding)

MongoDB 支持自动分片。分片是实现数据扩展的一种方法,依靠在跨服务器或者集群上进行数据分区来实现。一个最简单的实现是把所有的用户数据,按照名字首字母 A-M 放在服务器 1 ,然后剩下的放在服务器 2。谢天谢地,MongoDB 的拆分能力远比这种分法要强。分片不在本书的讨论范围之内,不过你应当有分片的概念,并且,当你的需求增长超过了使用单一副本集的时候,你应该考虑它。

尽管复制有时候可以提高性能(通过将长时间查询隔离到从服务器,或者降低某些类型的查询的延迟),它的主要目的是维护高可用性。分片是扩展 MongoDB 集群的主要方法。把复制和分片结合起来实现可扩展和高可用性是禁术。

状态(Stats)

你可以通过 db.stats() 查询数据库的状态。基本上都是关于数据库大小的信息。你还可以查询集合的状态,比如说 unicorns 集合,可以输入 db.unicorns.stats()。基本上都是关于集合大小的信息,以及集合的索引信息。

分析器(Profiler)

你可以这样执行 MongoDB profiler :

db.setProfilingLevel(2);

启动之后,我们可以执行一个命令:

db.unicorns.find({weight: {$gt: 600}});

然后检查 profiler:

db.system.profile.find()

输出会告诉我们:什么时候执行了什么,有多少文档被扫描,有多少数据被返回。

你要停止 profiler 只需要再调用一次 setProfilingLevel ,不过这次参数是 0。指定 1 作为第一个参数,将会过滤统计超过 100 milliseconds 的任务. 100 milliseconds 是默认的阈值,你可以在第二个参数中,指定不同的阈值时间,以 milliseconds 为单位:

//profile anything that takes
//more than 1 second
db.setProfilingLevel(1, 1000);

备份和还原

在 MongoDB 的 bin 目录下有一个可执行文件 mongodump 。简单执行 mongodump 会链接到 localhost 并备份你所有的数据库到 dump 子目录。你可以用 mongodump --help 查看更多执行参数。常用的参数有 --db DBNAME 备份指定数据库和 --collection COLLECTIONNAME 备份指定集合。你可以用 mongorestore 可执行文件,同样在 bin 目录下,还原之前的备份。同样, --db--collection 可以指定还原的数据库和/或集合。 mongodumpmongorestore 使用 BSON,这是 MongoDB 的原生格式。

比如,来备份我们的 learn 数据库导 backup 文件夹,我们需要执行(在控制台或者终端中执行该命令,而不是在 mongo shell 中):

mongodump --db learn --out backup

如果只还原 unicorns 集合,我们可以这样做:

mongorestore --db learn --collection unicorns \
    backup/learn/unicorns.bson

值得一提的是, mongoexportmongoimport 是另外两个可执行文件,用于导出和从 JSON/CSV 格式文件导入数据。比如说,我们可以像这样导出一个 JSON:

mongoexport --db learn --collection unicorns

CSV 格式是这样:

mongoexport --db learn \
    --collection unicorns \
    --csv --fields name,weight,vampires

注意 mongoexportmongoimport 不一定能正确代表数据。真实的备份中,只能使用 mongodumpmongorestore 。 你可以从 MongoDB 手册中读到更多的 备份须知

小结

在这章中我们介绍了 MongoDB 的各种命令,工具和性能细节。我们没有涉及所有的东西,不过我们已经把常用的都看了一遍。MongoDB 的索引和关系型数据库中的索引非常类似,其他一些工具也一样。不过,在 MongoDB 中,这些更易于使用。

总结

你现在应该有足够的能力开始在真实项目中使用 MongoDB 了。虽然 MongoDB 远不止我们学到的这些内容,但是你要作的下一步是,把学到的知识融会贯通,熟悉我们需要用到的功能。MongoDB website 有许多有用的信息。官网的 MongoDB user group 是个问问题的好地方。

NoSQL 不光是为需求而生,它同时还是不断尝试创新的成果。不得不承认,我们的领域是不断前行的。如果我们不尝试,一旦失败,我们就绝不会取得成功。就是这样的,我认为,这是让你在职业生涯一路走好的方法。

上一篇: 数据聚合