优化具有大数据的Linq:IN运算符

本文关键字:Linq IN 运算符 数据 优化 | 更新日期: 2023-09-27 18:24:15

如何优化此查询?

// This will return data ranging from 1 to 500,000 records
List<string> products = GetProductsNames(); 

List<Product> actualProducts = (from p in db.Products
                               where products.Contains(p.Name)
                               select p).ToList();

如果我发送一个44000个字符串的列表,这个代码需要大约30秒来填充actualProducts,不知道500000条记录需要什么。:(

有什么方法可以调整这个查询吗?

注意:每次调用(忽略第一个缓慢的edmx调用)几乎需要这么多时间

优化具有大数据的Linq:IN运算符

对500000条记录的IN查询总是一种病理情况。

首先,确保数据库中Name上有一个索引(可能不是聚集的)。

想法(都涉及到ADO.NET):

  • 使用"表值参数"传入值,并将INNER JOIN传递给TSQL中的表值参数
  • 或者创建具有列QueryId(可以是uniqueidentifier)和Name的形式为ProductQuery的表;发明一个guid来表示您的查询(Guid.NewGuid()),然后使用SqlBulkCopy将500000对(每行上的guid相同;不同的guid是不同的查询)快速推送到表中;然后使用TSQL在两个表之间执行INNER JOIN

事实上,这些都很相似,但第一个可能是第一个尝试的东西。设置较少。

如果您不想使用数据库,可以尝试使用Dictionary<string,string>

如果没有错的话,我怀疑products.Contains(p.Name)是昂贵的,因为它是O(n)运算。尝试将GetProductsNames返回类型更改为Dictionary<string,string>或将List转换为Dictionary

Dictionary<string, string> productsDict = products.ToDictionary(x => x);

所以您手头有一本字典,现在将查询重写为以下

List<Product> actualProducts = (from p in db.Products
                           where productsDict.ContainsKey(p.Name)
                           select p).ToList();

这将帮助您大大提高性能(缺点是分配双倍内存,优点是性能)。我用非常大的样本进行了测试,结果很好。试试看。

希望这能有所帮助。

您还可以使用散列方法,使用name列作为传递给散列函数的值;然后,您可以迭代500K集合,对每个名称进行哈希函数处理,并测试本地哈希文件中是否存在。这将需要比linq方法更多的代码,但它可能比对后端执行内部联接的重复调用快得多。