1

这似乎是一个常见的用例......但不知何故我无法让它工作。

我正在尝试将 MongoDB 用作具有唯一项的枚举存储。我创建了一个带有 byte[] Id(唯一 ID)和时间戳(长,用于枚举)的集合。该存储非常大(TB)并且分布在不同的服务器之间。我目前能够从头开始重建商店,因为我仍处于测试阶段。

我想做的是两件事:

  1. 为我插入的每个项目创建一个唯一的 ID。这基本上意味着如果我两次插入相同的 ID,MongoDB 将检测到这一点并给出错误。这种方法似乎工作正常。
  2. 通过其他进程不断枚举商店中的新商品。我采用的方法是向 InsertID 添加第二个索引,并在其上使用高精度时间戳以及服务器 id 和计数器(只是为了使其唯一和升序)。

在最好的情况下,这意味着枚举器将跟踪每个服务器的索引游标。根据我从 mongodb 查询处理中学到的知识,我期望这种行为。但是,当我尝试执行代码(如下)时,似乎需要很长时间才能得到任何东西。

        long lastid = 0;
        while (true)
        {
            DateTime first = DateTime.UtcNow;
            foreach (var item in collection.FindAllAs<ContentItem>().OrderBy((a)=>(a.InsertId)).Take(100))
            {
                lastid = item.InsertId;
            }
            Console.WriteLine("Took {0:0.00} for 100", (DateTime.UtcNow - first).TotalSeconds);
        }

我读过游标,但不确定它们是否满足将新项目插入商店时的要求。

正如我所说,我不受任何表结构或类似结构的约束......唯一重要的是我可以随着时间的推移获得新项目而不会获得重复项目。

-斯特凡。

4

1 回答 1

0

不知怎的,我想通了...或多或少...

我手动创建了查询,结果如下:

db.documents.find({ "InsertId" : { "$gt" : NumberLong("2020374866209304106") } }).limit(10).sort({ "InsertId" : 1 });

我在问题中提出的 LINQ 查询不会生成此查询。在对代码进行一些挖掘之后,我发现它应该是这个 LINQ 查询:

foreach (var item in collection.AsQueryable().Where((a)=>(a.InsertId > lastid)).OrderBy((a) => (a.InsertId)).Take(100))

AsQueryable() 似乎是执行 LINQ to MongoDB 查询重写的关键。

这给出了结果,但它们似乎仍然很慢(10 个结果为 4 秒,100 个结果为 30 秒)。但是,当我添加“解释()”时,我注意到查询执行中的“0 毫秒”。

我停止了批量插入和 tada 的过程,它可以工作,而且速度很快。换句话说:我遇到的问题是由于 MongoDB 的锁定行为,以及我解释 linq 实现的方式。由于前者是初始批量填充数据存储的结果,这意味着问题已解决。

在解决方案的“负面”部分:我更喜欢涉及可序列化游标或类似内容的解决方案......这个“采取”解决方案必须一遍又一遍地迭代 b-tree。如果有人对此有答案,请告诉我。

-斯特凡。

于 2012-07-09T07:54:40.383 回答