将多值与多值进行比较,保持性能
本文关键字:性能 比较 | 更新日期: 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 ; }
}