第七章 – 性能和工具
最后更新于:2022-04-01 00:55:07
在这章中,我们来讲几个关于性能的话题,以及在 MongoDB 开发中用到的一些工具。我们不会深入其中的一个话题,不过我们会指出每个话题中最重要的方面。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#索引index)索引(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](http://docs.mongodb.org/manual/indexes/) 获取更多关于索引的信息。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#explain)Explain
需要检查你的查询是否用到了索引,你可以通过 `explain` 方法:
~~~
db.unicorns.find().explain()
~~~
输出告诉我们,我们用的是 `BasicCursor` (意思是没索引), 12 个对象被扫描,用了多少时间,什么索引,如果有索引,还会有其他有用信息。
如果我们改变查询索引语句,查询一个有索引的字段,我们可以看到 `BtreeCursor` 作为索引被用到填充请求中去:
~~~
db.unicorns.find({name: 'Pilot'}).explain()
~~~
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#复制replication)复制(Replication)
MongoDB 的复制在某些方面和关系型数据库的复制类似。所有的生产部署应该都是副本集,理想情况下,三个或者多个服务器都保持相同的数据。写操作被发送到单个服务器,也即主服务器,然后从它异步复制到所有的从服务器上。你可以控制是否允许从服务器上进行读操作,这可以让一些特定的查询从主服务器中分离出来,当然,存在读取到旧数据的风险。如果主服务器异常关闭,从服务中的一个将会自动晋升为新的主服务器继续工作。另外,MongoDB 的复制不在本书的讨论范围之内。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#分片sharding)分片(Sharding)
MongoDB 支持自动分片。分片是实现数据扩展的一种方法,依靠在跨服务器或者集群上进行数据分区来实现。一个最简单的实现是把所有的用户数据,按照名字首字母 A-M 放在服务器 1 ,然后剩下的放在服务器 2。谢天谢地,MongoDB 的拆分能力远比这种分法要强。分片不在本书的讨论范围之内,不过你应当有分片的概念,并且,当你的需求增长超过了使用单一副本集的时候,你应该考虑它。
尽管复制有时候可以提高性能(通过将长时间查询隔离到从服务器,或者降低某些类型的查询的延迟),它的主要目的是维护高可用性。分片是扩展 MongoDB 集群的主要方法。把复制和分片结合起来实现可扩展和高可用性是禁术。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#状态stats)状态(Stats)
你可以通过 `db.stats()` 查询数据库的状态。基本上都是关于数据库大小的信息。你还可以查询集合的状态,比如说`unicorns` 集合,可以输入 `db.unicorns.stats()`。基本上都是关于集合大小的信息,以及集合的索引信息。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#分析器profiler)分析器(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);
~~~
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#备份和还原)备份和还原
在 MongoDB 的 `bin` 目录下有一个可执行文件 `mongodump` 。简单执行 `mongodump` 会链接到 localhost 并备份你所有的数据库到 `dump` 子目录。你可以用 `mongodump --help` 查看更多执行参数。常用的参数有 `--db DBNAME` 备份指定数据库和`--collection COLLECTIONNAME` 备份指定集合。你可以用 `mongorestore` 可执行文件,同样在 `bin` 目录下,还原之前的备份。同样, `--db` 和 `--collection` 可以指定还原的数据库和/或集合。 `mongodump` 和 `mongorestore` 使用 BSON,这是 MongoDB 的原生格式。
比如,来备份我们的 `learn` 数据库导 `backup` 文件夹,我们需要执行(在控制台或者终端中执行该命令,而不是在 mongo shell 中):
~~~
mongodump --db learn --out backup
~~~
如果只还原 `unicorns` 集合,我们可以这样做:
~~~
mongorestore --db learn --collection unicorns \
backup/learn/unicorns.bson
~~~
值得一提的是, `mongoexport` 和 `mongoimport` 是另外两个可执行文件,用于导出和从 JSON/CSV 格式文件导入数据。比如说,我们可以像这样导出一个 JSON:
~~~
mongoexport --db learn --collection unicorns
~~~
CSV 格式是这样:
~~~
mongoexport --db learn \
--collection unicorns \
--csv --fields name,weight,vampires
~~~
注意 `mongoexport` 和 `mongoimport` 不一定能正确代表数据。真实的备份中,只能使用 `mongodump` 和 `mongorestore` 。 你可以从 MongoDB 手册中读到更多的 [备份须知](http://docs.mongodb.org/manual/core/backups/) 。
## [](https://github.com/geminiyellow/the-little-mongodb-book/blob/master/zh-cn/mongodb.markdown#小结-6)小结
在这章中我们介绍了 MongoDB 的各种命令,工具和性能细节。我们没有涉及所有的东西,不过我们已经把常用的都看了一遍。MongoDB 的索引和关系型数据库中的索引非常类似,其他一些工具也一样。不过,在 MongoDB 中,这些更易于使用。