Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: Базы данных, ADO.NET
Войти
Регистрация
Восстановить пароль
 
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
1

Добавление больших объемов данных

07.12.2015, 12:09. Просмотров 299. Ответов 11
Метки нет (Все метки)

Доброго времени суток. Разрабатываю веб-приложение, в качестве бд использую MS SQL для доступа к данным Entity. Мне нужно загрузить 93к данных, они добавляются около 3 часов.. подскажите как сделать быстрее.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
while (adreses.Count != 0)
                {
                    count += adreses.Count;
                    foreach (var c in adreses)
                    {
                           AddSrteet(c);
                        AddHause(c);
                        AddUltip(c);
                        db.SaveChanges();
                    }
                    adreses = aiPrx.next().ToList();
                }
        private void AddSrteet(AddressAccount adres)
        {
            int code= Convert.ToInt32(adres.roadNetElemNameCode);
            if (db.RVC_SULIC.Where(p => p.KODUL ==code).Count() == 0)
            {
                RVC_SULIC row = new RVC_SULIC();
                  row.KODUL = code;
                  row.NAME = adres.roadNetworkElementName + " " + adres.roadNetworkElement;
                row.ULTIP = adres.roadNetworkElement;
                db.RVC_SULIC.Add(row);
            }
        }
        private void AddUltip(AddressAccount adres)
        {
            int code = Convert.ToInt16(adres.roadNetElemCode);
            if (db.RVC_SULICTIP.Where(p => p.ULTIP == code).Count() == 0)
            {
                RVC_SULICTIP row = new RVC_SULICTIP();
                row.ULTIP = code;
                row.FNAME = "new";
                row.NAME = adres.roadNetworkElement;
                db.RVC_SULICTIP.Add(row);
            }
        }
        private void AddHause(AddressAccount adres)
        {
            if (db.RVC_BDOM.Where(p => p.accountNumber == adres.accountNumber).Count() == 0)
            {
                int code = Convert.ToInt32(adres.roadNetElemNameCode);
                RVC_BDOM row = new RVC_BDOM();
                row.KODUL = code;
                row.NDOM = adres.buildingNum.ToString() + (adres.buildingBis != "" ? "к" : "") + adres.buildingBis;
                row.FLAT = adres.apartmentNum.ToString()+adres.apartmentInd;
                row.accountNumber = adres.accountNumber;
                db.RVC_BDOM.Add(row);
            }
        }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.12.2015, 12:09
Ответы с готовыми решениями:

Хранение больших объемов данных в файлах.
Добрый день. Столкнулся с проблемой необходимо хранить и обработывать большое...

Обработка больших данных в Access
Здравствуйте! Вопрос заключается в следующем, у меня есть несколько БД...

Зависает при приёме больших данных
не могу разобраться что я делаю с потоком входящих данных не так, при входе...

Добавление данных через форму в таблицу базы данных MS SQL
Здравствуйте! Я делаю форму для добавления записи в таблицу базы данных,...

Добавление данных видео, открытого из формы, в базу данных
Доброе время суток. Будьте добры подскажите, как сделать что бы в Visual...

11
insite2012
Модератор
Эксперт .NET
4858 / 3813 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
07.12.2015, 14:00 2
Цитата Сообщение от valdi_korot Посмотреть сообщение
93к
Это сколько в килограммах?
0
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
07.12.2015, 14:25  [ТС] 3
insite2012, 930 000 строк
0
insite2012
Модератор
Эксперт .NET
4858 / 3813 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
07.12.2015, 14:34 4
valdi_korot, первое что я вижу - несколько методов в цикле. А вот в каждом из ник, если я правильно понял, у вас идет дублирование кода. Я вот про эту строку:
Цитата Сообщение от valdi_korot Посмотреть сообщение
C#
1
int code= Convert.ToInt32(adres.roadNetElemNameCode);
Зачем так сделано? Не логичнее ли вычислить это значение один раз и передавать в каждый из методов?
0
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
07.12.2015, 14:44  [ТС] 5
insite2012, еще вопрос будет быстрее сразу очистить всю базу и добавлять все подрят, либо все же проверять на существующие данные ?
0
kolorotur
Эксперт .NET
10617 / 8798 / 2195
Регистрация: 17.09.2011
Сообщений: 15,073
Завершенные тесты: 1
07.12.2015, 14:46 6
Цитата Сообщение от valdi_korot Посмотреть сообщение
подскажите как сделать быстрее.
Перво-наперво нужно найти причину падения производительности.

Сначала уберите весь код, который работает с базой.
Если не умеете пользоваться профайлером, то делайте "по-дедовски" — сначала закомментируйте вот эти строчки:
C#
1
2
3
4
5
db.SaveChanges();
db.RVC_SULIC.Add(row);
db.RVC_SULICTIP.Add(row);
db.RVC_SULICTIP.Add(row);
db.RVC_BDOM.Add(row);
И прогоните алгоритм.
За сколько он завершится?
Если все равно будет работать долго, то дело не в EF и тема должна быть в другом разделе.
Если отработает быстро, то раскомментируйте по одной строчке, начиная с последней, каждый раз прогоняя приложение и сравнивая производительность.

Пока что видно две причины тормозов:
1. SaveChanges вызывается на каждой итерации, а не один раз после всего цикла.
2. В контексте включено отслеживание изменений, что приводит к постепенному падению производительности по мере добавления элементов.

Определите, что убивает производительность: вызов SaveChanges в цикле или вызов Add, оттуда уже и будем плясать.
0
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
07.12.2015, 15:17  [ТС] 7
kolorotur,
500 записей добавило за 59 908 мс из моего исходного текста,
за 59 664 мс save после цикла,
за 59 386 мс без Add и Save,
а вот и проблема похоже, без селекта к базе за 3 млс

Добавлено через 1 минуту
Цитата Сообщение от kolorotur Посмотреть сообщение
2. В контексте включено отслеживание изменений, что приводит к постепенному падению производительности по мере добавления элементов.
где это отключается ? не сталкивался с таким

Добавлено через 13 минут
kolorotur, но тогда мне приходится удалять предыдущие записи, а удаляет их тоже долго
C#
1
2
3
4
 db.RVC_SULIC.RemoveRange(db.RVC_SULIC.ToList());
                db.RVC_BDOM.RemoveRange(db.RVC_BDOM.ToList());
                db.RVC_SULICTIP.RemoveRange(db.RVC_SULICTIP.ToList());
                db.SaveChanges();
0
kolorotur
Эксперт .NET
10617 / 8798 / 2195
Регистрация: 17.09.2011
Сообщений: 15,073
Завершенные тесты: 1
07.12.2015, 15:45 8
Цитата Сообщение от valdi_korot Посмотреть сообщение
без селекта к базе
А вот селект к базе в условии я и не приметил.
Конечно, если 93к раз делать выборку из базы, то это убьет любую производительность.

Цитата Сообщение от valdi_korot Посмотреть сообщение
где это отключается ?
В вашем контексте, который db:
C#
1
2
3
4
5
6
7
class MyDbContext : DbContext
{
   public MyDbContext()
   {
      this.Configuration.AutoDetectChangesEnabled = false;
   }
}
Но тогда вам придется вручную каждую сущность устанавливать как добавленную, измененную или удаленную.

Цитата Сообщение от valdi_korot Посмотреть сообщение
тогда мне приходится удалять предыдущие записи, а удаляет их тоже долго
Для вашего сценария (добавление/обновление больших объемов в базе) EF плохо приспособлена: основное ее назначение — работа с небольшим набором данных, а-ля "обновить профайл на фэйсбучике".

Для обновления базы я бы использовал обычный низкоуровневый SQL-запрос и следующий алгоритм:
1. Создание временной таблицы с такой же структурой, как у обновляемой.
2. Заливка всех записей во временную таблицу через BULK INSERT
3. Обновление/добавление записей в обновляемую таблицу из временной через MERGE INTO.
4. Удаление временной таблицы.

Таким образом, пусть база занимается нахождением разницы.

Для остальных операций по нахождению/добавлению/изменению отдельных записей можно использовать и EF.
0
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
07.12.2015, 15:59  [ТС] 9
kolorotur, но что тогда использовать в с# для такого низкого уровня запроса ?
0
kolorotur
Эксперт .NET
10617 / 8798 / 2195
Регистрация: 17.09.2011
Сообщений: 15,073
Завершенные тесты: 1
07.12.2015, 16:04 10
Цитата Сообщение от valdi_korot Посмотреть сообщение
что тогда использовать в с# для такого низкого уровня запроса ?
SqlCommand + SqlBulkCopy

Как вариант, конечно, можно через EF сначала вытащить из базы все ID, а потом каждую добавляемую запись проверять на наличие, но если таблица большая, то это займет много времени на запрос и памяти на хранение всех ключей.
1
off
89 / 89 / 44
Регистрация: 20.04.2008
Сообщений: 326
Завершенные тесты: 3
08.12.2015, 08:23 11
Статья на эту тему http://habrahabr.ru/post/251397/
2
valdi_korot
50 / 50 / 31
Регистрация: 04.03.2014
Сообщений: 430
Завершенные тесты: 1
08.12.2015, 14:29  [ТС] 12
Нашел еще одно решение! можно использовать Dapper, во многом похож на EF
ссылка
0
08.12.2015, 14:29
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.12.2015, 14:29

Потоковая передача больших данных по TCP из Java в C#
Добрый день, Прошу помощи в разборе полетов: Задача: передать картинку с...

Добавление данных в таблицу и удаление данных из таблицы
Всем доброго время суток. Столкнулся с такой проблемой нужно написать программу...

Добавление, изменение и удаление данных в базе данных
Методом научного тыка кое как подключил таблицу Microsoft Access с помощью...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru