在這章中,我們來講幾個關于性能的話題,以及在 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 中,這些更易于使用。