搜索列表的Foreach循环性能

时间:2016-05-16 13:31:17

标签: c# performance loops

我有一个文档信息的SQL表,以及一个包含这些文档的安全信息的第二个表。

有超过200万个文档行,超过600万行包含安全信息。

我需要连接安全信息并将其保存回文档表[Security]列。

目前似乎是foreach循环中的瓶颈,每个文档都会在 securityLines 列表中搜索其安全策略集合。

这是我目前的工作代码

public static Task ApplyDocumentSecurity()
{
    return Task.Run(() =>
    {
        int totalDocCount = 0;
        int take = 5000;
        using (MyEntities db = new MyEntities ())
        {
            // get total document count
            totalDocCount = db.MigrationMasters.Count();
        }

        for (int i = 0; i < totalDocCount; i = i + take)
        {                
            using (MyEntities context = new MyEntities ())
            {
                var objectContext = (context as IObjectContextAdapter).ObjectContext;
                objectContext.CommandTimeout = 3600; // 1 hour

                // get the next 5,000 entries
                var documents = (from d in context.MigrationMasters
                          where d.Security == null
                          select new { d.ID, d.DocNum, d.Version }).Take(take).ToList();

                // get a list of the unique docnums
                var uniqueDocNums = documents.Select(x => x.DocNum).Distinct();

                // retrieve all the security policies for those documents                   
                var securityLines = new List<DocumentSecurity>();
                securityLines = context.DocumentSecurities
                                          .Where(s => uniqueDocNums.Contains(s.DocNum)).ToList();  

                // loop through each document and get the security policies from 
                // the short list now in memory             
                 List<Task> taskList = new List<Task>();

                    foreach (var document in documents)
                    {
                        var localCopyDoc = document;

                        // the below task may be running on another thread
                        var task = Task.Run(() =>
                        {
                            var securityLinesMatch = (from s in securityLines
                                                      where s.DocNum == localCopyDoc.DocNum && s.Version == localCopyDoc.Version
                                                      select s).ToList();

                            // manipulate security lines and join them, then save.
                            string acl = JoinSecurityLines(securityLinesMatch);
                            using (MyEntities context2 = new MyEntities())
                            {
                                var docToUpdate = context2.MigrationMasters.Find(localCopyDoc.ID);
                                docToUpdate.Security = String.IsNullOrEmpty(acl) ? "<Default>" : acl;
                                context2.SaveChanges();
                            }
                        });
                        taskList.Add(task);
                    }                   
                    Task.WaitAll(taskList.ToArray());
           }                 
       }
   });
}

基准:

在0.84分钟内完成5,000个完成20,000个文档。在大约8分钟内完成了200,000次。所以我要等80分钟才能完成。

在0.88分钟内完成10,000份已完成的20,000份文件。所以稍微慢一点,大概是因为它有一个更大的securityLines列表来搜索每个文档。

还有另外一种方法会更快吗?我尝试在一个LINQ查询中选择文档并加入安全性,虽然它更干净,但它的速度远远低于我在这里的速度。

0 个答案:

没有答案