MongoDB频繁更新索引

时间:2018-07-28 02:28:42

标签: mongodb indexing bulk

我正在为某些情况而苦苦挣扎。已经经历了所有文档和堆栈溢出,但是仍然找不到解决我的问题的完美方法。直接进入主题:

我收集了一百万个具有以下结构的文档:

Example = {
  a: {1,2,3},
  b: Number,
  c: Number,
  d: String (short, usually up to 3-4 chars)
  e: String (length around 30-30 chars),
  f: Number
}

要求是允许用户通过以下方式搜索文档:

  • a的值之一,
  • b和c的最小值和最大值
  • f的最小值,
  • 检查d是否在最多10个值的数组中
  • 在e上执行正则表达式搜索
  • 允许按b,c或f排序(所有降序)

以下是一些用于a,b,c,f过滤器的UI,并进行了排序以获得更好的图片:

filters and sorting

我通过以下方式构造过滤器对象:

{
 if sort by b then b: {$gt: ...}, c: {$gt:...,$lt:...}
 else c: {$gt: ...}, b: {$gt:...,$lt:...}

 a: ...,

 if set f then f: { $gt:...},

 if set e then e: { $regex: ...},

 if set d then d: { $nin: ... }
}

所以我的查询可能像这样:

Example.find({b: {$lt: 1}, c: {$gt: 1, $lt: 2}, a: 2, f: { $gt: 0}, 
e: {$regex: ...}, d: {$nin: [...]}).sort({b: -1}).skip(...).limit(...)

我当前的索引如下:

{a: 1}
{b: -1, c: -1, a: 1, f: -1, e: 1, d: 1}
{b: -1, c: -1, a: 1, e: 1, d: 1}
{b: -1, a: 1, f: -1, e: 1, d: 1}
{c: -1, a: 1, f: -1, e: 1, d: 1}
{a: 1, f: -1, e: 1, d: 1, a: -1}

,当我看到用户更频繁地使用它们时,我会不断添加新的。

此外,我需要经常更新b,d和c值(使用批量api尽可能快地进行更新,但老实说,它不能比整个集合的几分钟更快)。我尝试了不同的方法,但最终为“ a”字段的每个值创建了单独的cron,并像这样更新它们:

let counter = 0;
let limitNo = 2222; 
let bulk = collection.initializeUnorderedBulkOp();
let docCount = ...;

await collection.find({a: aValue}).forEach(function(exampleDoc){
    counter++;  
    docCount --;
    limitNo--;  

    let dataToUpdate = getUpdatedData(exampleDoc);

    bulk.find({_id: exampleDoc._id}).updateOne({$set:dataToUpdate});
    if(limitNo === 0 || docCount === 0){
        bulk.execute();
        bulk = collection.initializeUnorderedBulkOp();
        limitNo = 2222;
    }
})

顺便说一句,像这样迭代,我偶尔会得到“ MongoError:未找到光标ID 34884445099”,该问题本应该在MongoDB 4.0(https://jira.mongodb.org/browse/SERVER-34810)中解决,但显然不是,或者我做错了

我的问题是:

  1. 如何使其更快?我最终创建了大约10个索引 但恐怕会拖慢整个更新过程。而且,从数据库获取记录似乎很慢(2-3秒)
  2. 是真的,我应该将更具选择性的字段放在第一位 索引?
  3. 是否应该将“最慢的”字段放在索引的末尾?
  4. 当过滤器字段为 可选的?有没有比创建更好的方法呢? 每种可能的组合?也许我不应该允许用户 该字段可选吗?
  5. 也许对整体架构有什么建议?我最近从MySQL转移到安静的地方,但对Mongo仍然没有信心。
  6. 很显然,我尝试使用“解释”,但没有太多 有关我对结果的关注的信息。
  7. 我还担心在“ e”字段上使用正则表达式。 20-30 字符长,正则表达式表达式检查是否不包含     一些值(最多可以包含40个)。     以前我使用的是array和$ nin,但是由于速度很慢,所以决定     将所有值合并为字符串并对其进行正则表达式搜索。
  8. 我也在考虑创建只读副本,并仅在该副本上创建索引,而普通数据库则没有任何副本     索引,更新起来会更快。这是个好主意吗?
  9. 有时由于某些原因,在使用组合过滤器进行搜索时,mongo仅使用{a:1}索引。你知道为什么吗?
  10. 我最终应该使用{background:true}选项创建包含经常更新的字段的索引吗?我对此案有不同的看法。
  11. 最后我应该切换到另一个数据库吗?我了解不同的数据库可以满足不同的用途,所以也许     就我而言,使用Mongo不好吗?
  12. 其他问题:当我进行这些批量更新时,我有很多这样的日志:

    update示例命令:{q:{_id:ObjectId('5b56c6420257245fe5c97a41')},u:{$ set:{b:1,c:1.2,f:3.7}},multi:false,upsert:false} planSummary:IDHACK keysExamined:1 docsExamined:1 nMatched:1 nModified:1 keysInserted:5 keysDeleted:5 numYields:1 locks:{全局:{acquisitionCount:{r:420,w:420}},数据库:{acquisitionCount:{w :420}},集合:{quireCount:{w:420}}} 380ms

    为什么只更新1个单文档而不是全部文档?

感谢您的帮助。我真的非常感谢任何提示,因为我已经为此苦了一个月。

0 个答案:

没有答案