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

时间:2015-06-18 21:35:30

标签: c# performance linq tsql database-performance

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

库存记录和产品记录都将代码值存储在单独的表中。每条记录都有一个值记录,并且是外键输入主表。

我正在尝试 来编写此代码,因为从性能角度来看,我知道它会运行数天。

 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存储过程。

2 个答案:

答案 0 :(得分:1)

您的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))
 });

现在所有这些都转移到了数据库。查看查询计划,看看这是否已经可以接受,或者我们是否需要调整它。由于非SARGable谓词,这可能是一个讨厌的交叉产品加过滤器。

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

答案 1 :(得分:1)

  

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

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

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

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  ; }
}