将多值与多值进行比较,保持性能

本文关键字:性能 比较 | 更新日期: 2023-09-27 17:57:06

我有两种形式的记录或数据。一个是库存记录,另一个是产品。

库存记录和产品记录的代码值都存储在单独的表中。 每条记录都有一个值记录,并外键连接到主表。

我尽量不要在下面写这段代码,因为我知道从性能的角度来看它会运行数天。

 public void test(product _Product)
        {
            DBDataContext db = new DBDataContext();

            var ProductCodes = db.tbl_ProdCodeValues.Where(x=>x.productID == _Product.productID);
            foreach (var code in ProductCodes)
            {
                var matches = db.InventoryCodeValues.Any(x => x.InventoryValue.ToLower().Contains(code.ProdCodeValue));
            }
        }

将一个值集合与另一个值集合进行比较的最佳方法是什么? 如果您认为任务或多线程方法也可以提高性能,请告诉我。

每个产品可能有大约 1-1000 个值,库存将始终有超过 100 万个值,并且仍在增长。所以性能是关键,因为数学会告诉你有大量的比较正在执行。如果需要,我还可以将查询从 LINQ 移动到 SQL 再到 T-SQL 存储过程。

将多值与多值进行比较,保持性能

你的foreach就像一个Select

var ProductCodes = db.tbl_ProdCodeValues.Where(x=>x.productID == _Product.productID);
var withMatches =
 ProductCodes
 .Select(code => new {
  code,
  matches = db.InventoryCodeValues.Any(x => x.InventoryValue.ToLower().Contains(code.ProdCodeValue))
 });

现在所有这些远程数据库。查看查询计划,看看这是否已经可以接受,或者我们是否需要对此进行调整。由于该不可 SARG 的谓词,这可能是一个令人讨厌的交叉乘积加过滤器。

InventoryCodeValues是什么格式?这是一个分隔的列表吗?如果将列表拆分为行,则可以使用简单的==谓词,并使此查询以线性时间而不是二次时间运行。

将一组值与另一个值进行比较的最佳方法是什么 值的集合。

所提出的方法包括创建一个合并两种记录类型的列表,并根据匹配标准对合并的列表进行排序。

排序后,您将按顺序识别和处理匹配项。在下面的代码中,我假设比较的代码值是字符串。

public class Member 
{ 
  internal string Key ; 
  internal int    Source ; 
  internal object DataObject ;
  internal Member(string key,string source,object dataobject)
  { // source identifies the source, e.g "P" for Prod and "I" for Inventory
    Key = key ;
    Source = Source ; 
    DataObject = dataobject 
  }
}
// create and fill the merged list  
List<Member> list = new List<member>();
for (int i=0;i<db.tbl_ProdCodeValues.Count;i++) 
{
  string prodcodevalue = ... ; // set the value here
  object prodcodeobject= ... ; // set the record object here
  list.Add(new Member(prodcodevalue,1,prodcodeobject) ;
}
for (int i=0;i<db.tbl_InventoryCodeValues.Count;i++) 
{
  string inventorycodevalue= ... ; // set the value here
  object inventorycodeobject= ... ; // set the record object here
  list.Add(new Member(inventorycodevalue,2,inventorycodeobject) ;
}
// sort the merged list 
list.Sort(delegate(Member x, Member y) { return (x.Key+" "+x.Source).CompareTo(y.Key+" "+y.Source); });
// Process the merged list
// we assume that a key cannot be empty
list.Add(new Member("",0,null) ; // just for proper termination of next loop
string CurKey="" ;
int starti=-1 ; int endi=-1 ; 
int startp=-1 ; int endp=-1 ;  
for (int n=0;n<list.Count;n++)
{
  if (list[n].Key==CurKey) { if (list[n].Source="I") endi=n ; if (list[n].Source="P") endp=n ;
  else 
  {
    if (CurKey!="" ) 
    { // -------- Process the CurKey for matches ---------
      // The Prod      records corresponding to CurKey are given by list[p].dataobject whith p from startp to endp  
      // The Inventory records corresponding to CurKey are given by list[i].dataobject whith i from starti to endi 
      // if either starti or startp is negative, there is no match
      ... // insert your business code there
    }
    if (list[n].Source="I") { starti=endi=n  ; startp=endp=-1 ; }
    if (list[n].Source="P") { starti=endi=-1 ; startp=endp=n  ; }
}