2013-04-20 154 views
2

當輸入數據是單個值並且收集數據包含最小/最大範圍時,在Mongo中查找數據的最有效方式是什麼?例如:在mongo中搜索範圍

record = { min: number, max: number, payload } 

需要查找記錄中的最小/最大範圍內的數字。範圍從不相交。關於範圍的大小沒有可預測性。

集合中有~6M條記錄。如果我解壓縮範圍(每個值都有範圍記錄),我會查看約4B記錄。

我創建的{min:1,max:1}複合索引,但嘗試使用搜索:

db.block.find({min:{$lte:value},max:{$gte:value}) 

...時間介於幾到幾十秒鐘。以下是explain()getIndexes()的輸出。有什麼技巧可以使搜索執行速度顯着加快?

NJmongo:PRIMARY> db.block.getIndexes() 
[ 
    { 
      "v" : 1, 
      "key" : { 
        "_id" : 1 
      }, 
      "ns" : "mispot.block", 
      "name" : "_id_" 
    }, 
    { 
      "v" : 1, 
      "key" : { 
        "min" : 1, 
        "max" : 1 
      }, 
      "ns" : "mispot.block", 
      "name" : "min_1_max_1" 
    } 
] 


NJmongo:PRIMARY> db.block.find({max:{$gte:1135194602},min:{$lte:1135194602}}).explain() 
{ 
    "cursor" : "BtreeCursor min_1_max_1", 
    "isMultiKey" : false, 
    "n" : 1, 
    "nscannedObjects" : 1, 
    "nscanned" : 1199049, 
    "nscannedObjectsAllPlans" : 1199050, 
    "nscannedAllPlans" : 2398098, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 7534, 
    "nChunkSkips" : 0, 
    "millis" : 5060, 
    "indexBounds" : { 
      "min" : [ 
        [ 
          -1.7976931348623157e+308, 
          1135194602 
        ] 
      ], 
      "max" : [ 
        [ 
          1135194602, 
          1.7976931348623157e+308 
        ] 
      ] 
    }, 
    "server" : "ccc:27017" 
} 
+0

這很長時間 - 你有多少RAM?這是什麼版本的MongoDB?你可以在查詢運行時運行mongostat並捕獲它的輸出嗎? – 2013-04-20 03:33:20

+0

@AsyaKamsky就像Leopd所說的那樣,它並不是真的意外,數據庫必須搜索大量記錄(查看解釋輸出)。除非MongoDB支持幾何索引,否則這只是生活中的事實,或者我必須使用一些技巧(現在評估他):) – 2013-04-20 08:24:21

+0

它確實支持2d索引,但它們的語義含義是專門針對地理位置的。如果你想出一些聰明的應用程序,它仍然可能適用於你。 – Leopd 2013-04-20 16:33:20

回答

1

如果您block記錄的範圍從來沒有重疊,那麼你就可以做到這一點與更快:

db.block.find({min:{$lte:value}}).sort({min:-1}).limit(1) 

這個查詢將返回幾乎是瞬間,因爲它可以找到記錄與簡單的查找中該指數。

您正在運行的查詢速度很慢,因爲兩個子句分別匹配數百萬個必須合併的記錄。事實上,我認爲您的查詢在minmax上的單獨索引運行速度更快(可能快得多),因爲您的複合索引的max部分只能用於給定的min - 不搜索具有特定max的文檔。

+0

這正是我正在尋找的。我需要添加的唯一東西 - 是如果找到元素(如範圍中有空洞),則檢查'max'的值。謝謝! – 2013-04-20 08:36:58

+0

不同之處在於,您對查詢速度緩慢的原因不正確 - 沒有兩個子句返回將被合併的數百萬個子句。問題在於,索引的主要部分使用的不平等性不足以提供選擇性。 – 2013-04-21 06:17:02

+0

@Asya同意最大的問題是'max'上沒有可用的索引,所以它必須掃描集合。但我認爲,爲了這個策略,真正高效的mongo將不得不支持目前還沒有的索引交叉:https://jira.mongodb.org/browse/SERVER-3071 – Leopd 2013-04-22 16:08:49