通过C#写入MongoDB的写入速度慢且不一致

时间:2017-10-17 07:43:19

标签: c# .net mongodb performance

问题: 我们的写入速度很慢,写入时间差异很大。从1分钟到近4分钟。这是为了插入大量的值(准确地说是704 974)

背景: 我们从txt文件中读取值,将其链接到某个标记(数据对象),然后将值添加到值集合中。每个数据点都链接到标签和时间。每个值bson都有两个主键:ID和tag-date。 Bson的值如下所示:

public int InsertValues(string aDatabaseName, List<cValueDocument> aValues, out List<int> aErrorValueIndexes,
        bool aOverride = false)
    {
        Parallel.ForEach(aValues, aValue => aValue.ConvertToDoubleIfCan());
        int lResult = 0;
        Stack<int> lErrorIndexesToDelete = new Stack<int>(aValues.Count - 1);

        aErrorValueIndexes = new List<int>(aValues.Count);
        aDatabaseName = aDatabaseName.ToLower();

        var lValueCollection =
            MongoDatabasesDict[aDatabaseName].GetCollection<cValueDocument>(tMongoCollectionNames.Value.ToString());
        var lTagCollection =
            MongoDatabasesDict[aDatabaseName].GetCollection<cTagDocument>(tMongoCollectionNames.Tag.ToString());

        List<cValueDocument> lValuesOrderedByTime = aValues.OrderBy(aDocument => aDocument.Timestamp).ToList();

        // Check if there are Values that belong to other Tags.
        if (lValuesOrderedByTime.Any(aValue => aValue.TagID != lValuesOrderedByTime[0].TagID))
        {
            return -4;
        }

        cTagDocument lTagDocument = lTagCollection.AsQueryable().First(aTag => aTag._id == lValuesOrderedByTime[0].TagID);

        // Find any Values that are not at least the minimum Interval between each other.
        for (int i = 1; i < lValuesOrderedByTime.Count; i++)
        {
            // Determine if the two consecutive timestamps are not at least an Interval from each other.
            if (lTagDocument.IntervalMask.CompareDateTimesWithinInterval(lValuesOrderedByTime[i - 1].Timestamp, lValuesOrderedByTime[i].Timestamp) == -1)
            {
                aErrorValueIndexes.Add(aValues.FindIndex(aElement => aElement == lValuesOrderedByTime[i]));
                lErrorIndexesToDelete.Push(i);
                lResult = -2;
            }
        }

        // Determine if erroneous values must be removed before insertion.
        if (lResult == -2)
        {
            // Remove each value with an index in lErrorIndexesToDelete;
            while (lErrorIndexesToDelete.Count > 0)
            {
                lValuesOrderedByTime.RemoveAt(lErrorIndexesToDelete.Pop());
            }
        }

        if (aOverride)
        {//removed for testing purposes}

        try
        {
            try
            {
                InsertManyOptions lOptions = new InsertManyOptions();
                lOptions.IsOrdered = false;
                lValueCollection.InsertMany(lValuesOrderedByTime, lOptions);
            }
            catch (MongoBulkWriteException lException)
            {
                if (lException.WriteErrors?.First().Code == 11000)
                {
                    aErrorValueIndexes = Enumerable.Range(0, aValues.Count).ToList();
                    lResult = -3;
                }
                else
                {
                    throw;
                }
            }

            return lResult;
        }
        catch (Exception lException)
        {
            BigDBLog.LogEvent("Error, an exception was thrown in InsertValues. ", tEventEscalation.Error,
                false,
                lException);
            return -5;
        }
    }

mongoDb设置为3复制集,我们用writeconcern写入true(我们遇到一个复制集落后并且拒绝自动赶上的麻烦)Mongo在MESOS / Linux部署上运行,而c#代码通过网络从Windows机器连接。

Mongo版本:3.4.5

C#驱动程序:2.4.4

我还将最小和最大线程池线程数增加了50.我利用线程尝试提高写入速度,它有点起作用。

代码 将数据插入mongo的实际代码是:

{{1}}

我删除了一些值检查以缩短功能。 基本上该函数将aValues推送到mongo

调试/跟踪 这是对我来说很奇怪的地方。我使用相同的文件来测试它。我在每次测试之前删除了DB中的值。

执行速度从1分钟到4分钟不到1分钟。 我使用jetbrains dotTrace对程序进行了跟踪。它指向MongoDB.Driver.Core.Misc.StreamExtensionMethods.ReadBytes作为热点。如果您遵循代码,则称为MongoDB.Driver.MongoCollectionBase`1.InsertMany。这很奇怪,因为我正在编写数据库而不是从中读取数据。 CPU使用spike(在文件转换期间更多),但保持低(1-2%)。

我查看了wiredTiger.concurrentTransactions票证。他们没有用完。

问题

  1. 如何提高读取速度(最差时为3175个/秒) 8392个值/秒)?
  2. 为什么我会有这样的不一致?我真的不相信它可以与网络相关。
  3. 为什么它会如此多地读取字节,为什么会这样做 瓶颈?
  4. 我还可以做些什么来帮助找到问题?

0 个答案:

没有答案