Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 利用大数据优化Linq:IN算子_C#_Linq_Optimization - Fatal编程技术网

C# 利用大数据优化Linq:IN算子

C# 利用大数据优化Linq:IN算子,c#,linq,optimization,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)

如何优化此查询

// 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();
//这将返回1到500000条记录的数据
列出产品=GetProductsNames();
列出实际产品=(从数据库产品中的p开始)
其中products.Contains(p.Name)
选择p.ToList();
此代码大约需要30秒来填充
实际产品
如果我发送44000个字符串的列表,不知道500000条记录需要多少时间:(

有没有办法调整这个查询

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

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

在中查询500000条记录时,总是会出现病态情况

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

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

  • 使用“表值参数”传入值,并将
    内部联接
    传递给TSQL中的表值参数
  • 或者,创建一个
    ProductQuery
    格式的表,其中包含列
    QueryId
    (可以是
    uniqueidentifier
    )和
    Name
    ;创建一个guid来表示查询(
    guid.NewGuid()
    ),然后使用
    SqlBulkCopy
    来推送500000对(每行都有相同的guid;不同的guid是不同的查询)非常快速地输入到表中;然后使用TSQL在两个表之间执行
    内部联接

实际上,它们非常相似,但第一个可能是第一件要尝试的事情。设置更少。

如果您不想使用数据库,您可以尝试使用
字典

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

Dictionary<string, string> productsDict = products.ToDictionary(x => x);
字典产品dict=products.ToDictionary(x=>x);
因此,您手头有一本词典,现在按如下所示重写查询

List<Product> actualProducts = (from p in db.Products
                           where productsDict.ContainsKey(p.Name)
                           select p).ToList();
列出实际产品=(来自数据库产品中的p
其中productsDict.ContainsKey(p.Name)
选择p.ToList();
这将帮助您大大提高性能(缺点是您分配了双内存,优点是性能)。我使用非常大的样本进行了测试,结果很好。请尝试一下


希望这会有所帮助。

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

从哪里获取信息?为什么不在查询中使用联接?@jonsket来自文本文件。一个包含500000个产品的文本文件?为什么不使用数据库?文本文件中的记录是从另一台服务器导出的,我们没有这样做o检查本地商店中有多少产品。(仅用于同步商品)在尝试此操作后,您会得到回复。是否可以在代码中创建临时表而不更改edmx?或者是否有任何方法可以尝试我们建议的临时表而不修改edmx?@UsmanAzam据我所知,EF不会使用这些方法。因此,确实-不需要编辑edmx,因为编辑edmx什么也做不到。这是一个“关于这个特定查询,请访问ADO.NET/TSQL”的问题。请记住:EF只是一个工具;您可以使用多个工具。有时,您需要放下锤子,拿出螺丝刀。@UsmanAzam我不会这么匆忙地“接受”直到你有机会尝试它,但是……这肯定是我做的第一件事,我不想匆忙。我们的另一个应用程序和你建议的一样。它寻找参数,如果它们在25以上,则临时在数据库中,通过“代码>连接< /代码>查询”进行其余操作。C++在使用SQL LyLand。我在论坛上问这个问题只是因为是否有更好的解决方案。@UsmanAzam关于表值参数的要点是,如果您熟悉“表变量”,它可以避免创建临时表然后:基本上是这样,但作为参数是的,可能只是在内存中提取所有产品更快。这取决于行的数量和结构。@usr我尝试了一个使用列表的查询,该查询执行时间为73秒,切换到Dictionary@SriramSakthivel哇,太棒了,如果这个黑客能表现得这么好的话然后我一定会在回去工作(办公室)的时候尝试一下。无论如何,谢谢:)