[英]How to run in parallel a query from synchronous code in C# via Entity Framework
My goal is to speed up a query, and I thought to leverage parallelism, lets assume that I have 2,000 items in ids list, and I split them to 4 lists each one with 500 ids, and I want to open 4 treads that each one will create a DB call and to unite their results, in order to achieve that I used Parallel.ForEach, but it did not improved the performance of the query because apparently it does not well suited to io bound operations: Parallel execution for IO bound operations我的目标是加快查询速度,我想利用并行性,假设我在 ids 列表中有 2,000 个项目,我将它们分成 4 个列表,每个列表有 500 个 id,我想打开 4 个踏板,每个将创建一个 DB 调用并统一它们的结果,以实现我使用 Parallel.ForEach,但它并没有提高查询的性能,因为它显然不太适合 io 绑定操作:IO 绑定操作的并行执行
The code in the if block uses parallel for each, vs the code in the else block that do it in a regular foreach. if 块中的代码对每个都使用并行,而 else 块中的代码在常规 foreach 中执行。
The problem is that the method that contains this query is not async (because it is in a very legacy component) and it can not be change to async, and basically I want to do parallel io bound calculation inside non async method (via Entity Framework).问题是包含此查询的方法不是异步的(因为它在一个非常旧的组件中)并且不能更改为异步,基本上我想在非异步方法中进行并行 io 绑定计算(通过实体框架)。
What are the best practices to achieve this goal?实现这一目标的最佳实践是什么? I saw that maybe I can use Task.WaitAll()
for that, I do not care to blocking the thread that runs this query, I am more concerned that something will went wrong with the Task.WaitAll()
that is called from a non async method我看到也许我可以为此使用Task.WaitAll()
,我不在乎阻塞运行此查询的线程,我更担心从非调用的Task.WaitAll()
会出现问题异步方法
I use Entity Framework as ORM over a SQL database, for each thread I opens a separate context because the context is not thread safe.我在 SQL 数据库上使用实体框架作为 ORM,对于每个线程,我打开一个单独的上下文,因为上下文不是线程安全的。
Maybe the lock that I use is the one that cause me the problem, I can change it to a ConcurrentDictionary
.也许我使用的锁是导致我出现问题的锁,我可以将其更改为ConcurrentDictionary
。
The scenario depicted in the code below is simplified from the one I need to improve, in our real application I do need to read the related entities after I loaded there ids, and to perform a complicated calculation on them.下面代码中描述的场景是我需要改进的场景,在我们的实际应用程序中,我确实需要在加载 id 后读取相关实体,并对它们执行复杂的计算。
Code:代码:
//ids.Bucketize(bucketSize: 500) -> split one big list, to few lists each one with 500 ids
IEnumerable<IEnumerable<long>> idsToLoad = ids.Bucketize(bucketSize: 500);
if (ShouldLoadDataInParallel())
{
object parallelismLock = new object();
Parallel.ForEach(idsToLoad,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
(IEnumerable<long> bucket) =>
{
List<long> loadedIds = GetIdsQueryResult(bucket);
lock (parallelismLock)
{
allLoadedIds.AddRange(loadedIds );
}
});
}
else
{
foreach (IEnumerable<long> bucket in idsToLoad)
{
List<long> loadedIds = GetIdsQueryResult(bucket);
allLoadedIds.AddRange(loadedIds);
}
}
What are the best practices [for running multiple queries in parallel]? [并行运行多个查询]的最佳实践是什么?
Parallel.ForEach with seperate DbContext/SqlConnection is a fine approach.带有单独的 DbContext/SqlConnection 的 Parallel.ForEach 是一种很好的方法。
It's just that running your queries in parallel is not really helpful here.只是并行运行查询在这里并没有真正的帮助。
If your 4 queries hit 4 separate databases, then you might get a nice improvement.如果您的 4 个查询命中 4 个单独的数据库,那么您可能会得到很好的改进。 But there's many reasons why running 4 separate queries in parallel on a single instance might not be faster than running a single large query.但是有很多原因导致在单个实例上并行运行 4 个单独的查询可能不会比运行单个大型查询更快。 Among these are blocking, resource contention, server-side query parallelism, and duplicating work between the queries.其中包括阻塞、资源争用、服务器端查询并行性以及查询之间的重复工作。
And so所以
My goal is to speed up a query, and I thought to leverage parallelism我的目标是加快查询速度,我想利用并行性
And so this is not usually a good approach to speeding up a query.因此,这通常不是加快查询速度的好方法。 There are, however, many good ways to speed up queries, so if you post a new question with the details of the query and perhaps some sample data you might get some better suggestions.但是,有许多加快查询速度的好方法,因此,如果您发布一个新问题,其中包含查询的详细信息以及一些示例数据,您可能会得到一些更好的建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.