3

如何优化这个查询?

// 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 个字符串的列表,则此代码大约需要 30 秒才能填充actualProducts,不知道 500,000 条记录需要什么。:(

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

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

4

3 回答 3

4

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

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

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

  • 使用“表值参数”将值传递INNER JOIN给 TSQL 中的表值参数
  • ProductQuery或者,创建一个包含列QueryId(可以是uniqueidentifier)和Name;的表格。发明一个 guid 来表示您的Guid.NewGuid()查询SqlBulkCopyINNER JOIN然后使用 TSQL在两个表之间做一个

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

于 2013-07-20T20:04:59.303 回答
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();

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

希望这可以帮助。

于 2013-07-20T20:26:57.967 回答
0

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

于 2013-07-21T00:05:23.313 回答