简体   繁体   English

如何通过实体框架从 C# 中的同步代码并行运行查询

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM