2012-03-28 59 views
4

我需要一些建議來創建和排序mongo中的索引。如何在mongodb中構造複合索引

我有一個收集後用5個屬性:

帖子

  • 狀態
  • 開始日期
  • 結束日期
  • lowerCaseTitle
  • 中將sortOrder

幾乎所有的帖子都會有相同的狀態1,只有少數人會有被拒絕的狀態。我所有的查詢都會過濾狀態,開始和結束日期,並按sortOrder進行排序。我也會有一個查詢在標題上進行正則表達式搜索。

我應該在{status:1,start:1,end:1,sort:1}上設置複合鍵嗎?我把這些字段放在複合索引中的順序是否重要 - 我應該首先將狀態放在複合索引中,因爲它是最廣泛的嗎?對每個房產做一個複合指數而不是單一指數會更好嗎? mongo只對任何給定的查詢使用單個索引嗎?

如果我正在做的正則表達式查詢lowerCaseTitle有索引嗎?

樣本查詢是:

db.posts.find({status: {$gte:0}, start: {$lt: today}, end: {$gt: today}}).sort({sortOrder:1}) 

db.posts.find({lowerCaseTitle: /japan/, status:{$gte:0}, start: {$lt: today}, end: {$gt: today}}).sort({sortOrder:1}) 

回答

16

這是在一個職位有很多問題;)讓我去通過他們的實際順序:

  • 每個查詢都可以在最多一個索引的使用(除頂層$或條款等外)。這包括任何排序。
  • 由於上述原因,您肯定需要針對問題的複合索引而不是單獨的每場索引。
  • 由於數據集的選擇性非常有限,因此低基數字段(因此,數據集中具有很少唯一值的字段)通常應該不在索引中。
  • 複合指標中的字段順序,以及複合索引中每個字段的相對方向(例如「{name:1,age:-1}」)。在mongodb.org上有很多關於複合索引和索引字段方向的文檔,所以在這裏我不再重複。
  • 如果排序字段位於索引中,並且是緊接在用於選擇結果集的最後一個字段之後的索引中的字段,排序將僅使用索引。在大多數情況下,這將是索引的最後一個字段。

所以,你不應該在你的指數包括地位可言的,因爲一旦指數走已經消除基於它最多將留下其中的大多數情況下,2-3文檔更高的基數領域的絕大多數文件幾乎沒有通過狀態索引進行優化(尤其是因爲您提到這些2-3個文檔很可能具有相同的狀態)。

現在,與您的情況相關的最後一個註釋是,當您使用範圍查詢(並且您是)時,它將不會使用索引進行排序。您可以通過在測試查詢後查看explain()的「scanAndOrder」值來檢查這一點。如果該值存在且爲真,則表示它將對結果集進行內存排序(掃描和排序),而不是直接使用索引。這在您的具體情況下無法避免。

所以,你的指數因此應該是:

db.posts.ensureIndex({start:1, end:1}) 

和您的查詢(修改爲清楚起見順序而已,查詢優化器將通過相同的執行路徑運行原來的查詢,但我更喜歡把索引字段第一和order):

db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1}) 
+1

排序鍵不應總是在用於查詢的最後一個鍵之後。如果提前使用排序鍵,則排序會在修剪之前進行。 [這篇文章](http://architects.dzone.com/articles/cardinal-ins-mongodb-query)說明了這是有用的。 – 2013-06-30 00:21:05

+0

有趣。我會做一些測試來看看實際的真實世界的性能特點。我不得不說,我有點懷疑這是永遠在現實世界情況下的性能改進(讀;大數據集,範圍查詢的高選擇性) – 2013-07-04 09:54:37

+0

@RemonvanVliet關於基數和忽略索引前綴優化,應複合索引鍵按最高到最低基數還是從最低到最高排序?我查閱了涉及複合索引的mongodb文檔,並對這個具體問題做出了回答;儘管我假設從最高到最低。另外:從2.6開始,mongodb支持索引交集的2個索引。 – zamnuts 2015-01-19 21:18:32

相關問題