如何优化此查询?
// 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调用)
答案 0 :(得分:4)
对500,000条记录的IN
查询始终是一个病态案例。
首先,确保数据库中的Name
上有一个索引(可能是非群集的)。
创意(都涉及到ADO.NET):
INNER JOIN
传递给TSQL中的table-valued-parameter ProductQuery
,其中包含QueryId
列uniqueidentifier
和Name
;发明一个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方法更多的代码,但它可能比重复调用后端进行内部连接要快得多。