C#, EF Core 3, параллелизм, как добиться параллельной обработки с операциями записи / чтения в базу данных SQL правильно? - PullRequest
0 голосов
/ 18 февраля 2020

Я нахожусь в центре проекта импорта данных, у меня есть старая БД, из которой я извлекаю данные, выполняю большую обработку, чтобы она "вписалась" в новую БД, а затем записываю ее в новую БД.

Я пытаюсь ускорить этот процесс, поскольку мне нужно обработать миллионы записей, а однопоточный процесс слишком медленный. В настоящее время я делаю это следующим образом:

SemaphoreSlim _sem = new SemaphoreSlim(8);

var tasks = policyVersionDictionary.Select(async pv =>
{

    await _sem.WaitAsync();

    await using (var dbThread = new ApplicationDbContext(connectionString))
    {

        try
        {
            dbThread.Database.SetCommandTimeout(240);

            var listOfPolicyVersions = pv.Value;

            var horseService = new HorseTransferServiceMultithreading(dbThread);

            await horseService.ProcessHorse(listOfPolicyVersions);

        }
        finally
        {
            _sem.Release();

            // Probably an overkill as we're inside 'using'
            dbThread.Database.CloseConnection();
            dbThread.Dispose();

        }
    }

}).ToArray();

await Task.WhenAll(tasks);  

_sem контролирует количество потоков, я создаю новый dbContext для каждого элемента в policyVersionDictionary, я также создаю новый HorseTransferServiceMultithreading, как я хочу он должен быть отдельным для каждой операции (потока).

метод horseService.ProcessHorse(listOfPolicyVersions); является методом-оболочкой для всей обработки, которую необходимо выполнить для каждого элемента, включая многократное чтение / запись в базу данных. .

Это уже работает быстрее, чем однопоточный способ сделать это, но я не уверен, является ли это правильным способом выполнения параллельной / параллельной обработки. Я прочитал тонну постов о бедствиях, которые случаются, когда вы пишете параллельный код, который читает / пишет из базы данных, взаимоблокировкам, ошибкам и всяким другим, но я недостаточно знаю об этом методе, чтобы понять, делаю это правильно или я совершаю огромную ошибку.

Есть ли лучший способ? Следует ли этого полностью избежать? Если да, то как следует решать импортируемые проекты, чтобы они были как можно быстрее? В настоящее время он работает около 48 часов (не только этот фрагмент кода), что довольно долго, и в идеале я хотел бы сделать его намного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...