Улучшение преобладанием обновления 40000 записей с помощью Entity рамки


У меня есть две таблицы, схемы и метки,

Circuit 
------------------
Id    Name  Path 

Tag
-----------
Id Name Circuit_Id

Теперь мне нужно перебрать все теги и обновлять каждый тег, где существует соответствующий путь и имя (путь замыкания и имя тега).

Я делаю это и он отлично работает , но очень медленно. Есть ли способ я могу улучшить скорость.

foreach (var tag in allPDUTags)
{
    var removedUnderScoreLast = tag.Path.Remove(tag.Path.LastIndexOf('_'));
    var removedUnderScoreLastButOne = removedUnderScoreLast.Remove(removedUnderScoreLast.LastIndexOf('_'));

    var circuitId = _context.Circuits.Where(c => c.Name == removedUnderScoreLastButOne).FirstOrDefault().Id;

    tag.Circuit_Id = circuitId;


    _counter++;

    if ((_counter % 1000) == 0)
    {
        Console.WriteLine($"Updated {_counter} of {totalsTags} Tags");
    }


}


140
-1
задан 22 марта 2018 в 04:03 Источник Поделиться
Комментарии
2 ответа

var circuitId = _context.Circuits.Where(c => c.Name == removedUnderScoreLastButOne).FirstOrDefault().Id;

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

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


  1. Изменить allPDUTags быть результатом соединения между контуром и тег.

  2. Если ты можешь бросать сущности основ написания SQL для обновления строк в оперативном порядке должна быть относительно простой, учитывая, что они оба находятся в таблицах базы данных. Я не уверен, СУБД вы используете, поэтому я не могу предоставить пример кода для этого.

  3. Быстрый и грязный будет поставить список цепей в памяти. Звоню _context.Цепях.Вызова метода toList() будет поместить их всех в памяти, а затем сравните этот список в цикле. Предполагается, что схемы достаточно мал, чтобы поместиться в память. Этот вариант не масштабируется-и я бы не советовал.

Я бы внимательно посмотреть на то, почему цепи.Путь и тег.Название должны быть синхронизированы в первую очередь. Там могут быть исторические причины или они могут быть в 2 разных баз данных/систем, но если они находятся в одном приложении я бы настоятельно не рекомендуется нормализовать базу данных и / или добавление ограничения, чтобы избежать необходимости синхронизации в первую очередь.

1
ответ дан 22 марта 2018 в 08:03 Источник Поделиться

Это подход к TSQL. Это должно быть довольно быстро.

declare @Circuit table (id int identity primary key, name varchar(20));
declare @Tag table (id int identity primary key, path varchar(40), circuitID int);
insert into @tag (path) values ('asld_aslkjf_alskd'), ('asxx_askjf_alsyd_ lasdj');
insert into @Circuit (name) values ('asld'), ('asxx_askjf');

select * from @tag;

update t
set t.circuitID = c.id
from @tag t
join @Circuit c
on c.name = reverse(SUBSTRING(REVERSE(t.path), CHARINDEX('_', REVERSE(t.path), CHARINDEX('_', REVERSE(t.path)) + 1) + 1, 100))
where t.circuitID <> c.id or t.circuitID is null;

select * from @tag

0
ответ дан 23 марта 2018 в 12:03 Источник Поделиться