【问题标题】:selecting linq list is slow选择 linq 列表很慢
【发布时间】:2023-03-12 22:38:01
【问题描述】:

当我尝试包含代码的注释部分时,选择很慢(获取 21k 需要 5 分钟 行)。

我可以做些什么来提高我的代码的性能

 var q = db.Storages.Where(x => x.LocationID == lngID && x.IsStored == true && x.Item.isInUse == false).ToList();


                if (q.Count() > 0)
                {

                    List<StorageMdl> lst = q.Select(x => new StorageMdl
                    {
                        lngID = x.ID,
                        strItemID = x.ItemID,
                        lngLocationID = x.LocationID,
                        itmMdl = new ItemMdl
                        {
                            strID = x.ID
                            //strBarCode = x.Item.Barcode,
                            //strColor = x.Item.Color,
                            //bolIsInUse = x.Item.isInUse,
                            //bolIsActive = x.Item.isActive,
                            //dteCreateDate = x.Item.CreateDate.Value,
                            //strDisposalRefNo = x.Item.DisposalRefNo,
                            //strCreatedBy = x.Item.CreatedBy,
                            ////dteDisposalDate = x.Item.DisposalDate.GetValueOrDefault(),
                            //itMdl = new ItemTypeMdl
                            //{
                            //    lngID = x.Item.ItemType.ID,
                            //    strName = x.Item.ItemType.Name,
                            //    bolHasBarcode = x.Item.ItemType.hasBarcode,
                            //    bolHasManyColors = x.Item.ItemType.hasManyColor,
                            //    strCreatedBy = x.Item.ItemType.CreatedBy,
                            //    dteCreateDate = x.Item.ItemType.CreateDate.HasValue ? (DateTime)x.Item.ItemType.CreateDate : new DateTime(),
                            //    bolIsActive = x.Item.ItemType.isActive
                            //},
                            //strITName = x.Item.ItemType.Name,
                            //strManufacturer = x.Item.Manufacturer,
                            //strDescription = x.Item.Description
                        },
                        bolIsStored = x.IsStored.HasValue ? (bool)x.IsStored : false,
                        strStoredBy = x.StoredBy,
                        strApprovedStoreBy = x.ApproveStoreBy,
                        dteStoredDate = x.StoreDate,
                        dteItemOut = x.ItemOutDate.HasValue ? (DateTime)x.ItemOutDate : new DateTime(),
                        strItemOutBy = x.ItemOutApproveBy
                    }).ToList();

提前谢谢你。 :)

【问题讨论】:

  • 您在内存中创建了 21000 个对象。你的机器是什么?恕我直言,如有必要,请尝试重新考虑。如果是网格,你也可以使用分页器。
  • 你有什么索引?这些将产生巨大的影响。
  • 没有注释掉的代码需要什么时间执行?
  • 从原始查询中尽可能多地构建 List&lt;StorageMdl&gt;,不要先将查询存储在 q 中,然后再循环返回,这简直太疯狂了。 (您知道您正在对数据库进行多少次往返吗?我的话。)只需从一开始就构建它。对于您将默认值代替空值的值,如有必要,请在事后执行此操作。当您合理地加载 21K 对象时,没有理由需要 5 分钟来加载它们(除非考虑到它的负载,您的数据库无法胜任任务)。
  • @AnthonyPegram 嗨,谢谢你的建议,也许我会这样做。无论如何,我只是想知道,因为我有一个使用相同选择方式的函数,但速度更快,唯一的区别是它从 Item 遍历到 ItemType,您认为我的问题与索引有关吗?

标签: c# asp.net-mvc linq


【解决方案1】:

我不确定您是如何检索数据的(例如正在运行的数据库系统、ORM 和其他东西)。但是从我看你可能有一个 n+1 的问题。

注释掉的代码确实访问了您的Storage 对象的Item 属性。它还访问Item 对象的ItemType 属性。也许您的 ORM(或其他)会延迟加载。这意味着它会为您创建的每个对象发出一个数据库查询。这将导致非常糟糕的表现。也许您附加了一些分析器并分析实际的数据库查询。

【讨论】:

  • 我的另一个函数也有同样的查询,但是它只从Item遍历到ItemType,它可以在一个短时间。您认为我的问题与索引有关吗?
  • 我不能说这是否是问题所在,但在用于过滤/连接的行上建立索引始终是一个好主意,并且可以提高性能。
【解决方案2】:

问题可能是您对导航属性的第二次选择(即 x.Item 或 x.Item.ItemType)对数据库进行多次往返,导致查询速度变慢。尝试运行您调用 .toList() 之前的整个查询

我不太确定存储表中的可空类型,但想法是:

List<StorageMdl> lst = db.Storages.Where(x => x.LocationID == lngID && x.IsStored == true && x.Item.isInUse == false)
                  .Select(x => new StorageMdl
                    {
                        lngID = x.ID,
                        strItemID = x.ItemID,
                        lngLocationID = x.LocationID,
                        itmMdl = new ItemMdl
                        {
                            strID = x.ID
                            strBarCode = x.Item.Barcode,
                            strColor = x.Item.Color,
                            bolIsInUse = x.Item.isInUse,
                            bolIsActive = x.Item.isActive,
                            dteCreateDate = x.Item.CreateDate.Value,
                            strDisposalRefNo = x.Item.DisposalRefNo,
                            strCreatedBy = x.Item.CreatedBy,
                            dteDisposalDate = x.Item.DisposalDate!=null ? x.Item.DisposalDate.Value : DateTime.MinValue,
                            itMdl = new ItemTypeMdl
                            {
                                lngID = x.Item.ItemType.ID,
                                strName = x.Item.ItemType.Name,
                                bolHasBarcode = x.Item.ItemType.hasBarcode,
                                bolHasManyColors = x.Item.ItemType.hasManyColor,
                                strCreatedBy = x.Item.ItemType.CreatedBy,
                                dteCreateDate = x.Item.ItemType.CreateDate!=null ? x.Item.ItemType.CreateDate.Value : DateTime.MinValue,
                                bolIsActive = x.Item.ItemType.isActive
                            },
                            strITName = x.Item.ItemType.Name,
                            strManufacturer = x.Item.Manufacturer,
                            strDescription = x.Item.Description
                        },
                        bolIsStored = x.IsStored!=null ? x.IsStored.Value : false,
                        strStoredBy = x.StoredBy,
                        strApprovedStoreBy = x.ApproveStoreBy,
                        dteStoredDate = x.StoreDate,
                        dteItemOut = x.ItemOutDate!=null ? x.ItemOutDate.Value : DateTime.MinValue,
                        strItemOutBy = x.ItemOutApproveBy
                    }).ToList();

【讨论】:

    【解决方案3】:

    我把之前的代码改成了这个

                    if (q.Count() > 0)
                    {
                        List<StorageMdl> a = db.Storages.Where(x => x.LocationID == lngID && x.IsStored == true && x.Item.isInUse == false)
                                               .Select(x => new StorageMdl
                                               {
                                                   lngID = x.ID,
                                                   strItemID = x.ItemID,
                                                   lngLocationID = x.LocationID,
                                                   itmMdl = new ItemMdl
                                                   {
                                                       strID = x.ID,
                                                       strBarCode = x.Item.Barcode,
                                                       strColor = x.Item.Color,
                                                       bolIsInUse = x.Item.isInUse,
                                                       bolIsActive = x.Item.isActive,
                                                       dteCreateDate = x.Item.CreateDate.Value,
                                                       strDisposalRefNo = x.Item.DisposalRefNo,
                                                       strCreatedBy = x.Item.CreatedBy,
                                                       dteDisposalDate = x.Item.DisposalDate,
                                                       itMdl = new ItemTypeMdl
                                                       {
                                                           lngID = x.Item.ItemType.ID,
                                                           strName = x.Item.ItemType.Name,
                                                           bolHasBarcode = x.Item.ItemType.hasBarcode,
                                                           bolHasManyColors = x.Item.ItemType.hasManyColor,
                                                           strCreatedBy = x.Item.ItemType.CreatedBy,
                                                           dteCreateDate = x.Item.ItemType.CreateDate ?? DateTime.Now,
                                                           bolIsActive = x.Item.ItemType.isActive
                                                       },
                                                       strITName = x.Item.ItemType.Name,
                                                       strManufacturer = x.Item.Manufacturer,
                                                       strDescription = x.Item.Description
                                                   },
                                                   bolIsStored = x.IsStored ?? false,
                                                   strStoredBy = x.StoredBy,
                                                   strApprovedStoreBy = x.ApproveStoreBy,
                                                   dteStoredDate = x.StoreDate,
                                                   dteItemOut = x.ItemOutDate ?? DateTime.Now,
                                                   strItemOutBy = x.ItemOutApproveBy
                                               }).ToList();
                        retVal.Add("exitCode", 1);
                        retVal.Add("list", lststored);
                    }
    

    而且比以前更快了。

    感谢您的所有帮助。 :)

    【讨论】:

      猜你喜欢
      • 2022-07-25
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 2018-04-25
      • 2022-01-18
      • 1970-01-01
      • 2013-04-08
      • 1970-01-01
      相关资源
      最近更新 更多