简体   繁体   English

C#LINQ-SQL帮助-查询超过10,000个项目的数据库

[英]C# LINQ-SQL Help - Querying DB over 10,000 items

I'm running into an issue with LINQ -> SQL speed at the moment. 目前,我遇到了LINQ-> SQL速度问题。 I am trying to retrieve over 10,000 products - Which is fine as the speed to retrieve just the code,name,description,id for these to a list is around 2 seconds. 我正在尝试检索10,000多种产品-这很好,因为将这些清单的代码,名称,描述和ID检索到列表的速度约为2秒。

My main issue is then trying to iterate over these 10,000 items to calculate the count of stock (Based on how many stock items (rows) than are matched in the db table). 然后,我的主要问题是尝试遍历这10,000个项目以计算库存数量(基于数据库表中匹配的库存项目(行)数)。 This of course makes over 10,000 calls to SQL to work this out - which takes a lot of time. 当然,要进行10,000次以上的SQL调用才能解决此问题-这需要大量时间。 I need this calculation to then base my filter to only those with a particular amount. 我需要进行此计算才能将过滤器仅基于具有特定数量的过滤器。

 IEnumerable<Product> filteredRecords = warehousing.GetProducts(wID);  // Takes under 2 seconds for 10k records

                var data = filteredRecords
                                .Select(p => new
                                {
                                    ID = p.ProductID,
                                    ProductName = p.Product.Name,
                                    ProductCode = p.Product.Code,                                        
                                    StockLevel = stock.GetTotalStockCount(p.ProductID, p.WarehouseID.Value)
                                }).OrderBy(l => l.StockLevel).ToArray();

Should I go down the path of trying to revert to Native Query to slightly increase the speed or should I opt for a background process that calculates the stock counts periodically and stores them into a separate table? 我应该选择尝试恢复到本机查询以稍微提高速度的方法,还是应该选择一个后台进程来定期计算库存数量并将它们存储在单独的表中?

I'm unsure of what is best practice/approach in this situation? 我不确定在这种情况下最佳做法/方法是什么?

Edit It's this calculation that's adding the penalty. 编辑正是这种计算增加了罚款。 Including the GetTotalStockCount method: 包括GetTotalStockCount方法:

        public int GetTotalStockCount(Int32? productID = null, Int32? warehouseID = null)
    {

        var query = from stockItem in _unitOfWork.StockItemRepository.Get(w => w.ProductID == productID).Select(s => s.LocationID)
                    join warehouseLocation in _unitOfWork.WarehouseLocationRepository.Get(w => w.WarehouseID == warehouseID && w.Type == WarehouseLocationType.Stock).Select(s => s.ID) on stockItem.Value equals warehouseLocation
                    select new { stockItem.Value };

        return query.Count();
    }

You should filter your data with StockCount and should not use ToArray until you really need. 您应该使用StockCount过滤数据,并且除非真正需要,否则不要使用ToArray

Try this: 尝试这个:

 IEnumerable<Product> filteredRecords = warehousing.GetProducts(wID);  // Takes under 2 seconds for 10k records

var data = filteredRecords
    .Select(p => new
    {
        ID = p.ProductID,
        ProductName = p.Product.Name,
        ProductCode = p.Product.Code,                                        
        StockLevel = stock.GetTotalStockCount(p.ProductID, p.WarehouseID.Value)
    }).Where(l => l.StockLevel > NEEDED_AMOUNT);

And consider move GetTotalStockCount method on database layer to filter your data there. 并考虑将GetTotalStockCount方法移至数据库层以在那里过滤数据。

You have two options: 您有两种选择:

  1. Probably you should consider to use view on database to generate this data, because GetTotalStockCount method cannot be translated to SQL query to speed up. 也许您应该考虑使用数据库视图来生成此数据,因为GetTotalStockCount方法无法转换为SQL查询以加快速度。 Of course it depends on complexity of GetTotalStockCount method. 当然,这取决于GetTotalStockCount方法的复杂性。

  2. In first query get records from Products, StockItem and WarehouseLocation and then group them by Products to get count aggregate 在第一个查询中,从Products,StockItem和WarehouseLocation获取记录,然后将它们按Products分组以获得总计计数

You need to change method GetTotalStockCount to get count from a memory list instead of database. 您需要更改方法GetTotalStockCount以从内存列表而不是数据库中获取计数。

So, first fetch and save the count from DB in a list and use that list inside function GetTotalStockCount. 因此,首先从数据库中获取计数并将其保存在列表中,然后在函数GetTotalStockCount中使用该列表。

The problem is that the GetTotalStockCount method is hitting the db in a separate, once for each record. 问题在于,GetTotalStockCount方法在单独的数据库中击中数据库,对于每个记录一次。 I'm not sure I have your db structure right here but you could try this: 我不确定我的数据库结构是否正确,但是您可以尝试以下方法:

.Select(p => new
    {
        ID = p.ProductID,
        ProductName = p.Product.Name,
        ProductCode = p.Product.Code,                                        
        StockLevel = p.StockItem.WarehouseLocation.Where(w => w.WarehouseID == p.WarehouseID.Value).Count()
    }).OrderBy(l => l.StockLevel).ToArray();

This will calculate the stock level item within the sql query and mean that there is only one db hit. 这将计算sql查询中的库存水平项目,并且意味着只有一个数据库命中。

NOTE: .StockITem.WarehouseLocation may change depending on how you db is structured but this is how I imagine it would look from you current query. 注意:.StockITem.WarehouseLocation可能会有所不同,具体取决于您的数据库的结构,但这是我想象的从您当前查询中看到的样子。

You could try the TSQL 您可以尝试使用TSQL

select p.ProductID, p.Product.Name, p.Product.Code, count(*)    
  from StockItemRepository p    
  join WarehouseLocationRepository w
    on p.ProductID = w.WarehouseID.Value    
   and w.Type == WarehouseLocationType.Stock   
 group by p.ProductID, p.Product.Name,  p.Product.Code

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM