使用大数据优化Linq:IN运算符

时间:2013-07-20 19:05:07

标签: c# linq optimization

如何优化此查询?

// 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();

如果我发送44,000个字符串列表,不知道500,000条记录需要什么,此代码大约需要30秒才能填充actualProducts。 :(

任何调整此查询的方法?

注意:每次通话都需要花费很多时间(忽略第一个慢速edmx调用)

3 个答案:

答案 0 :(得分:4)

对500,000条记录的IN查询始终是一个病态案例。

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

创意(都涉及到ADO.NET):

  • 使用“table值参数”传递值,并使用INNER JOIN传递给TSQL中的table-valued-parameter
  • 或者,创建一个表格ProductQuery,其中包含QueryIduniqueidentifierName;发明一个guid来表示你的查询(Guid.NewGuid()),然后使用SqlBulkCopy将500,000对(每行上相同的guid;不同的guid是不同的查询)推送到表中真的很快;然后使用TSQL在两个表之间执行INNER JOIN

实际上,这些非常相似,但第一个可能是第一个尝试。少设置。

答案 1 :(得分:1)

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

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

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

所以你手头有一本字典,现在重写下面的查询

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

这将有助于您提高性能(缺点是您分配双内存优势是性能)。我测试了非常大的样本,效果很好。尝试一下。

希望这有帮助。

答案 2 :(得分:0)

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