2014-11-14 37 views
1

目前,我有一个MongoDB的集合与以下类型的文件(〜1000个文档):蒙戈DB设计用于快速查询的范围

{ _id : "...", 
    id : "0000001", 
    gaps : [{start:100, end:110}, {start:132, end:166}...], // up to ~1k elems 
    bounds: [68, 88, 126, 228...],       // up to 100 elems 
    length: 300, 
    seq : "ACCGACCCGAGGACCCCTGAGATG..." 
} 

“差距”和阵列指的是“边界”值“seq”和“length”中的坐标是指“seq”长度。 我已经定义了“id”,“gaps”和“bounds”的索引。 我需要根据坐标范围进行查询。例如,给定“from = 100”和“to = 200”,我想为每个文档检索一个“间隙”的子数组,一个位于范围内的“bounds”和“seq”子字符串的子数组在这种情况下在100和200之间)。 眼下,这是使用以下聚集管道进行:

db.annot.aggregate(
     {$match : {"id" : "000001"}}, 
     {$unwind : "$gaps"}, 
     {$unwind : "$bounds"}, 
     {$match: { 
        $or :[ 
         {"gaps.start" : {$gte:from, $lte:to}}, 
         {"gaps.end" : {$gte:from, $lte:to}}, 
         {"bounds" : {$gte:from, $lte:to}} 
        ] 
        } 
     }, 
     {$project:{ 
       id:1, 
       gaps:1, 
       bounds:1, 
       subseq:{$substr:["$seq", from, (to-from)]}}}, 
     {$group : { 
       _id : "$id", 
       gaps : {"$addToSet" : "$gaps"}, 
       bounds : {"$addToSet" : "$bounds"}, 
       subseq : {"$first" : "$subseq"}}}, 
    )                               
  • 查询整个集合(留出在管道中的第一个“$匹配”)大约需要14秒。
  • 依次查询所有文档每个最多需要50毫秒(总共约19秒)。
  • 单独查询所有文档并行需要总共约7秒。
  • 使用只与id匹配的管道(即,使用管道中的第一个“$匹配”)查询总共花费约5秒。

什么是最好的数据库和查询设计,以最大限度地提高这类查询的性能?

+0

缺口和边界之间的关系是什么?麻烦的是双$ unwinds,它会把你的一个文档从它产生多达100 * 1000个文档,每一个对(间隙,边界)一个文档。另外,通过顺序查询和并行查询,你究竟意味着什么? – wdberkeley

+0

差距和界限之间没有关系。它们都是指seq字段的坐标,但它们没有彼此之间的关系。是的,我知道“$ unwinds”会为每个缺口/限定对创建单个文档,这就是为什么我想更改文档/收集格式的原因。通过“顺序”我的意思是我查询每个文件(例如)在for循环(上面的“聚合”查询)和“并行”我的意思是我创建不同的线程(多核心),并运行并行查询。 – emepyc

回答

1

什么是最好的数据库和查询设计,以最大限度地提高这种查询的性能?

既然你问到了提高你的代码和设计,我建议您切换到的mongodb最新版本,如果你还没有。这应该是一个很好的起点。对于这些类型的问题,基本思路应该是reducenumber of documentsinput到每个pipeline operation

我建议你有一个名为range一个额外的变量,它包含了所有的数字betweenfromto,包括两者。这使我们能够在bounds阵列上应用$intersection等功能。

所以变量,总操作从环境的需求应该是:

var from = x; var to = y; var range=[x,...,y]; 
  • 的第一步是要匹配的是有 idgaps子文档文件的数量和在bounds值我们的范围。此 减少说的文件被输入到下一级的数量500
  • 的下一步是$redact非符合间隙子 文档。该阶段现在适用于 上一步中筛选出的500个文档。
  • 第三步是我们的领域为$project作为我们的需要。

注意到我们需要的任何地方使用$unwind操作和实现的任务。

db.collection.aggregate([ 
{$match : {"id" : "0000001", 
      "gaps.start":{$gte:from}, 
      "gaps.end":{$lte:to}, 
      "bounds" : {$gte:from, $lte:to}}}, 
{$redact:{ 
     $cond:[ 
       {$and:[ 
         {$gte:[{$ifNull: ["$start", from]},from]}, 
         {$lte:[{$ifNull: ["$end", to]},to]} 
         ]},"$$DESCEND","$$PRUNE" 
       ] 
     }}, 
{$project: { 
      "bounds":{$setIntersection:[range,"$bounds"]}, 
      "id":1, 
      "gaps":1, 
      "length":1, 
      "subseq":{$substr:["$seq", from, (to-from)]}}} 
])