• 🚨 29 мая стартует курс «Пентест Active Directory: от теории к практике» от Академии Кодебай

    🔍 Изучите реальные техники атак на инфраструктуру Active Directory: от первоначального доступа до полной компрометации.
    🛠️ Освойте инструменты, такие как BloodHound, Mimikatz, CrackMapExec и другие.
    🧪 Пройдите практические лабораторные работы, имитирующие реальные сценарии атак.
    🧠 Получите знания, которые помогут вам стать востребованным специалистом в области информационной безопасности.

    После старта курса запись открыта еще 10 дней Подробнее о курсе ...

  • Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

Загрузка Dbf-файла, 1С 7.7

  • Автор темы Автор темы BBDragon
  • Дата начала Дата начала
B

BBDragon

В программе необходимо подгружать dbf-файл, содержащий порядка 400 000 записей. Сам файл содержит более 30 полей, из них загружается 21. Загрузку запустил в 05.07.2010г. в 15-40 по московскому времени, до сих пор она не завершена. Хотелось бы как-то оптимизировать алгоритм с целью увеличения быстродействия.

Код:
Процедура ВыборФайла()
КаталогЗагрузки = ""; 
ФайлЗагрузки = "";
Если ФС.ВыбратьФайл(1, ФайлЗагрузки, КаталогЗагрузки, "Выберите файл", "*.dbf|*.dbf", , ) = 1 Тогда
ФайлЗагрузки = КаталогЗагрузки + ФайлЗагрузки;	
КонецЕсли;
КонецПроцедуры	 

Процедура Сформировать() 
ИмФайл=СокрЛП(ФайлЗагрузки); 
ДБФ = СоздатьОбъект("XBase"); 
ДБФ.ОткрытьФайл(ИмФайл,,1);
ДБФ.Первая(); 
СпрПац = СоздатьОбъект("Справочник.Пациенты"); 
Пока ДБФ.ВКонце() = 0 Цикл 
Если (ДБФ.PR_IZM <> 2) Тогда // обрабатываем только неудаленные записи
СпрПац.Новый();
СпрПац.ФамилияПациента = СокрЛП(ДБФ.FAM); 
СпрПац.ИмяПациента= СокрЛП(ДБФ.IM);
СпрПац.ОтчествоПациента= СокрЛП(ДБФ.OT); 
Если СокрЛП(ДБФ.SEX)="1" Тогда
СпрПац.ПолПациента = "М"
Иначе СпрПац.ПолПациента = "Ж";
КонецЕсли;

СпрПац.ДатаРождения = СокрЛП(ДБФ.BIRTHDAY);
СпрПац.СерияНомерПолиса = СокрЛП(ДБФ.SERIES)+''+СокрЛП(ДБФ.NUMBER);
СпрПац.Регион = СокрЛП(ДБФ.REGION);
СпрПац.Район = СокрЛП(ДБФ.A_RN);
СпрПац.НасПункт = СокрЛП(ДБФ.A_NAS);
СпрПац.Улица = СокрЛП(ДБФ.A_STREET);
СпрПац.Дом = СокрЛП(ДБФ.A_DOM);
СпрПац.Корпус = СокрЛП(ДБФ.A_KORP);
СпрПац.Квартира = СокрЛП(ДБФ.A_KV);
СпрПац.Статус = СокрЛП(ДБФ.STATUS);
СпрПац.КодДокумента = СокрЛП(ДБФ.C_DOC);
СпрПац.СерияНомерДокумента = СокрЛП(ДБФ.SN_DOC);
СпрПац.РегионСтрахования = СокрЛП(ДБФ.REGIONS);
СпрПац.НомерДоговора = СокрЛП(ДБФ.N_DOG);
СпрПац.КодСМО = СокрЛП(ДБФ.KOD_SMO);
СпрПац.ДатаВыдачиПолиса = СокрЛП(ДБФ.DATE_VID); 

ДР=СокрЛП(ДБФ.DATE_OUT); 
ДатаСтрока = Формат(ДР, "ДДММГГГГ");
Если (ДатаГод(ДР)>1900) и (ДатаГод(ДР)<1950) Тогда // Загружена дата с 2001 по 2050 год
НоваяДата=Лев(ДатаСтрока,6) + "20" + Прав(ДатаСтрока,2); 
Иначе НоваяДата = ДатаСтрока; //обычная дата XX века
КонецЕсли;
СпрПац.ДатаОкончанияПолиса = НоваяДата;
СпрПац.ДатаИзмененияПолиса = СокрЛП(ДБФ.DATE_IZM);
СпрПац.Записать();

СпрПолис = СоздатьОбъект("Справочник.ПолисыСтраховыхКомпаний"); 
СпрПолисСерияНомер=СокрЛП(ДБФ.SERIES)+' '+СокрЛП(ДБФ.NUMBER);
Если СпрПолис.НайтиПоНаименованию(СпрПолисСерияНомер)=0 тогда	 
СпрПолис.Новый();
СпрПолис.СерииПолисов=СокрЛ(ДБФ.SERIES); 
СпрПолис.НачальныйНомерПолиса=СокрЛ(ДБФ.NUMBER); 
СпрПолис.Наименование=СокрЛ(ДБФ.SERIES)+' '+СокрЛ(ДБФ.NUMBER); 
СпрСтрах=СоздатьОбъект("Справочник.Контрагенты");
Если СпрСтрах.НайтиПоКоду(ДБФ.KOD_SMO)=0 тогда
СпрСтрах.Новый();
СпрСтрах.Код= СокрЛП(ДБФ.KOD_SMO);
СпрСтрах.Записать();
КонецЕсли;
СпрСтрахДок=СпрСтрах;
СпрПолис.СтраховаяКомпания=СпрСтрахДок.ТекущийЭлемент();
СпрПолис.Записать();
КонецЕсли;
ДБФ.Следующая();
КонецЕсли;
КонецЦикла;
Сообщить("Конец Загрузки");
ДБФ.ЗакрытьФайл(); 
КонецПроцедуры
 
Я с месяц назад делал тест
создавал 10.000 элементов справочника
пустых
это занимало в моей тестовой базе 30 минут

а у вас 400 - 800 тысяч элементов создается, кроме того другие действия

если, предположим, ваше железо в 5 раз быстрее моего, то все равно я бы прогнозировал, что не меньше чем сутки будет работать эта загрузка

ЗЫ можно было бы через каждые 1000 записей сообщение выдавать, хоть видно было бы чего ждать
 
ЗЫ можно было бы через каждые 1000 записей сообщение выдавать, хоть видно было бы чего ждать
А я бы вместо этого сообщения (или вместе с ним) предложил через 1000-10000 (число можно получить экспериментально) записей начинать - завершать транзакцию

Добавлено: И не могу удержаться от шпильки : скорость не бывает медленной (как и цена дешевой), она может быть НИЗКОЙ или ВЫСОКОЙ.
 
Всем спасибо за помощь!! Мне повезло и загрузка завершена спустя всего 18ч после начала :) Железо - Core 2 Duo E6750 @ 2,66 GhZ, RAM 2 Gb, XP SP2. Но вот незадача - вчера торопился к врачу, в спешке ткнул в списке выбора свою локальную базу, а не сетевую, с которой все работают. Хотелось бы избежать еще одной загрузки базы.. Ясное дело простым копированием файлов не обойтись, выгрузка и загрузка справочника займет также уйму времени. Что можно еще предпринять?
 
Ясное дело простым копированием файлов не обойтись, выгрузка и загрузка справочника займет также уйму времени
Если конфигурация одна и та же, что мешает тупо скопировать соответствующие файлы SC*.* ?
 
Если конфигурация одна и та же, что мешает тупо скопировать соответствующие файлы SC*.* ?
Уже пробовал, выдает "Нарушена структура данных таблицы SC30".
При поытке тестирования и исправления базы:

Таблица - SC30. Не сошлись типы полей номер 9(SP1306).
Проверка физической целостности таблиц ИБ. Неисправимая ошибка.
 
И еще о пользе транзакций.
Замечено, что 10 раз по 10000 читать из ДВФ-файла и писАть в справочник быстрее, чем один раз 100000.
Мне периодически приходится проделывать некие действия со справочником номенклатуры размером 50К через ДБФ-переходник, так что собственный опыт имею
 
а если 10000 раз по 10?
А еще можно попробовать забивать гвозди микроскопом :)

Добавлено: К тому же
СпрПолис = СоздатьОбъект("Справочник.ПолисыСтраховыхКомпаний");
СпрСтрах=СоздатьОбъект("Справочник.Контрагенты");
совершенно незачем делать в цикле
 
1. Создание объектов вынести за цикл.
2. Через каждые 100 строк фиксировать транзакцию (кстати, ускорение записи при использовании транзакций - это баг 7.7, ставший фичей).
А еще расскажите мне, как у вас вообще завершилась загрузка? Хотя, подозреваю, что просто всегда выполнялось условие...
Код:
Пока ДБФ.ВКонце() = 0 Цикл 
Если (ДБФ.PR_IZM <> 2) Тогда // обрабатываем только неудаленные записи
...
ДБФ.Следующая();
КонецЕсли;
КонецЦикла;
 
Через каждые 100 строк фиксировать транзакцию (кстати, ускорение записи при использовании транзакций - это баг 7.7, ставший фичей).
Когда фиксировать транзакцию, зависит, видимо, от железа.
У меня при фиксации через каждую тысячу все равно летает, так что обычно делаю через несколько тысяч
 
Поправил процедуру, поставил транзакцию через каждую тысячу - скорость фантастически возросла! По крайней мере 1500 записей загружает буквально за 3-4 секунды! Поставил на загрузку 400 000 записей, проверим, что получится в итоге)
Всем спасибо огромное за помощь :)))))
 
Прочитай и это для общего образования
https://codeby.net/threads/34828.html
Спасибо, почитал)

Увы, загрузка работает некорректно(
Загружается только первая запись из файла, причем 31 раз, а далее больше ничего не грузится. Естественно, что обработка очень быстро завершает свою работу. Я вчера на радостях забыл проверить, что в итоге попадает в справочник, вот и попал впросак..

Код:
		ИмФайл=СокрЛП(ФайлЗагрузки); 
ДБФ = СоздатьОбъект("XBase"); 
ДБФ.ОткрытьФайл(ИмФайл,,1);
ДБФ.Первая(); 
СпрПац = СоздатьОбъект("Справочник.Пациенты"); 
СпрПолис = СоздатьОбъект("Справочник.ПолисыСтраховыхКомпаний"); 
СпрСтрах=СоздатьОбъект("Справочник.Контрагенты");  

НачатьТранзакцию();
Для k=1 по ДБФ.КоличествоЗаписей() Цикл 
// заполнение спрвочника
Если Цел(((k/1000)-Цел(k/1000))*k)=0 Тогда //фиксируем транзакцию, если K - кратно тысяче
ЗафиксироватьТранзакцию();
КонецЕсли;
НачатьТранзакцию();
КонецЦикла;	 
ЗафиксироватьТранзакцию();


Думаю, что проблема в моем условии проверки k на кратность тысяче, но не могу понять, что у меня за ошибка.. :)
Подскажите, пожалуйста, каким образом вы фиксируете транзакции через 1000 записей?
 
Код:
КоличествоЗаписей = 0;
Пока ... Цикл
Если КоличествоЗаписей = 0 Тогда
НачатьТранзакцию();
КонецЕсли;
//что-то делаем

//что-то записываем
КоличествоЗаписей = КоличествоЗаписей + 1;

Если КоличествоЗаписей = 1000 Тогда
ЗафиксироватьТранзакцию();
КоличествоЗаписей = 0;
КонецЕсли;
КонецЦикла;
Если КоличествоЗаписей <> 0 Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
 
Код:
сч=1000;
НачатьТранзакцию();
Для k=1 по ДБФ.КоличествоЗаписей() Цикл 
// заполнение спрвочника
Если к=сч Тогда //фиксируем транзакцию, если K - кратно тысяче
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;	 
ЗафиксироватьТранзакцию();
И обнулять счетчик
 
Код:
КоличествоЗаписей = 0;
Пока ... Цикл
Если КоличествоЗаписей = 0 Тогда
НачатьТранзакцию();
КонецЕсли;
//что-то делаем

//что-то записываем
КоличествоЗаписей = КоличествоЗаписей + 1;

Если КоличествоЗаписей = 1000 Тогда
ЗафиксироватьТранзакцию();
КоличествоЗаписей = 0;
КонецЕсли;
КонецЦикла;
Если КоличествоЗаписей <> 0 Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;

Вновь заносится только первая запись, но уже ровно столько раз, сколько записей в файле)

TimeDontWait, не совсем понял какой счетчик вы предлагаете обнулять?
 
Код:
количество=1000;
сч=0;
НачатьТранзакцию();
Для k=1 по ДБФ.КоличествоЗаписей() Цикл 
сч=сч+1;
// заполнение спрвочника
Если количество=сч Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
сч=0;
КонецЕсли;
КонецЦикла;	 
ЗафиксироватьТранзакцию();
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!

Курс AD