1. Получи 30.000 рублей. Для получения денег необходимо принять участие в конкурсе авторов codeby. С условиями и призами можно ознакомиться на этой странице ...

    Внимание! Регистрация авторов на конкурс закрыта.

    Скрыть объявление
  2. Требуются разработчики и тестеры для проекта codebyOS. Требования для участия в проекте: Знание принципов работы ОС на базе Linux; Знание Bash; Крайне желательное знание CPP, Python, Lua; Навыки системного администрирования. Подробнее ...

    Скрыть объявление

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

Тема в разделе "Базы данных и администрирование", создана пользователем BBDragon, 6 июл 2010.

  1. BBDragon

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    В программе необходимо подгружать 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);
    СпрСтрах.Записать();
    КонецЕсли;
    СпрСтрахДок=СпрСтрах;
    СпрПолис.СтраховаяКомпания=СпрСтрахДок.ТекущийЭлемент();
    СпрПолис.Записать();
    КонецЕсли;
    ДБФ.Следующая();
    КонецЕсли;
    КонецЦикла;
    Сообщить("Конец Загрузки");
    ДБФ.ЗакрытьФайл(); 
    КонецПроцедуры
     
  2. Hryv

    Hryv Гость

    Репутация:
    0
    Я с месяц назад делал тест
    создавал 10.000 элементов справочника
    пустых
    это занимало в моей тестовой базе 30 минут

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

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

    ЗЫ можно было бы через каждые 1000 записей сообщение выдавать, хоть видно было бы чего ждать
     
  3. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    А я бы вместо этого сообщения (или вместе с ним) предложил через 1000-10000 (число можно получить экспериментально) записей начинать - завершать транзакцию

    Добавлено: И не могу удержаться от шпильки : скорость не бывает медленной (как и цена дешевой), она может быть НИЗКОЙ или ВЫСОКОЙ.
     
  4. Hryv

    Hryv Гость

    Репутация:
    0
    согласен на счет транзакций
     
  5. BBDragon

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    Всем спасибо за помощь!! Мне повезло и загрузка завершена спустя всего 18ч после начала :) Железо - Core 2 Duo E6750 @ 2,66 GhZ, RAM 2 Gb, XP SP2. Но вот незадача - вчера торопился к врачу, в спешке ткнул в списке выбора свою локальную базу, а не сетевую, с которой все работают. Хотелось бы избежать еще одной загрузки базы.. Ясное дело простым копированием файлов не обойтись, выгрузка и загрузка справочника займет также уйму времени. Что можно еще предпринять?
     
  6. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    Если конфигурация одна и та же, что мешает тупо скопировать соответствующие файлы SC*.* ?
     
  7. BBDragon

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    Уже пробовал, выдает "Нарушена структура данных таблицы SC30".
    При поытке тестирования и исправления базы:

    Таблица - SC30. Не сошлись типы полей номер 9(SP1306).
    Проверка физической целостности таблиц ИБ. Неисправимая ошибка.
     
  8. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    И еще о пользе транзакций.
    Замечено, что 10 раз по 10000 читать из ДВФ-файла и писАть в справочник быстрее, чем один раз 100000.
    Мне периодически приходится проделывать некие действия со справочником номенклатуры размером 50К через ДБФ-переходник, так что собственный опыт имею
     
  9. Hryv

    Hryv Гость

    Репутация:
    0
    а если 10000 раз по 10? :)
     
  10. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    А еще можно попробовать забивать гвозди микроскопом :)

    Добавлено: К тому же
    совершенно незачем делать в цикле
     
  11. vitfil

    vitfil IT-интегратор

    Репутация:
    0
    Регистрация:
    2 апр 2004
    Сообщения:
    2.062
    Симпатии:
    0
    1. Создание объектов вынести за цикл.
    2. Через каждые 100 строк фиксировать транзакцию (кстати, ускорение записи при использовании транзакций - это баг 7.7, ставший фичей).
    А еще расскажите мне, как у вас вообще завершилась загрузка? Хотя, подозреваю, что просто всегда выполнялось условие...
    Код:
    Пока ДБФ.ВКонце() = 0 Цикл 
    Если (ДБФ.PR_IZM <> 2) Тогда // обрабатываем только неудаленные записи
    ...
    ДБФ.Следующая();
    КонецЕсли;
    КонецЦикла;
     
  12. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    Когда фиксировать транзакцию, зависит, видимо, от железа.
    У меня при фиксации через каждую тысячу все равно летает, так что обычно делаю через несколько тысяч
     
  13. BBDragon

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    Поправил процедуру, поставил транзакцию через каждую тысячу - скорость фантастически возросла! По крайней мере 1500 записей загружает буквально за 3-4 секунды! Поставил на загрузку 400 000 записей, проверим, что получится в итоге)
    Всем спасибо огромное за помощь :)))))
     
  14. vbs

    vbs Well-Known Member

    Репутация:
    0
    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
  15. BBDragon

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    Спасибо, почитал)

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

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

    Думаю, что проблема в моем условии проверки k на кратность тысяче, но не могу понять, что у меня за ошибка.. :)
    Подскажите, пожалуйста, каким образом вы фиксируете транзакции через 1000 записей?
     
  16. vitfil

    vitfil IT-интегратор

    Репутация:
    0
    Регистрация:
    2 апр 2004
    Сообщения:
    2.062
    Симпатии:
    0
    Код:
    КоличествоЗаписей = 0;
    Пока ... Цикл
    Если КоличествоЗаписей = 0 Тогда
    НачатьТранзакцию();
    КонецЕсли;
    //что-то делаем
    
    //что-то записываем
    КоличествоЗаписей = КоличествоЗаписей + 1;
    
    Если КоличествоЗаписей = 1000 Тогда
    ЗафиксироватьТранзакцию();
    КоличествоЗаписей = 0;
    КонецЕсли;
    КонецЦикла;
    Если КоличествоЗаписей <> 0 Тогда
    ЗафиксироватьТранзакцию();
    КонецЕсли;
     
  17. TimeDontWait

    TimeDontWait Well-Known Member

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

    BBDragon Well-Known Member

    Репутация:
    0
    Регистрация:
    4 май 2008
    Сообщения:
    148
    Симпатии:
    0
    Вновь заносится только первая запись, но уже ровно столько раз, сколько записей в файле)

    TimeDontWait, не совсем понял какой счетчик вы предлагаете обнулять?
     
  19. TimeDontWait

    TimeDontWait Well-Known Member

    Репутация:
    0
    Регистрация:
    4 янв 2010
    Сообщения:
    367
    Симпатии:
    0
    Код:
    количество=1000;
    сч=0;
    НачатьТранзакцию();
    Для k=1 по ДБФ.КоличествоЗаписей() Цикл 
    сч=сч+1;
    // заполнение спрвочника
    Если количество=сч Тогда
    ЗафиксироватьТранзакцию();
    НачатьТранзакцию();
    сч=0;
    КонецЕсли;
    КонецЦикла;	 
    ЗафиксироватьТранзакцию();
     
  20. vitfil

    vitfil IT-интегратор

    Репутация:
    0
    Регистрация:
    2 апр 2004
    Сообщения:
    2.062
    Симпатии:
    0
    Значит, дело не в транзакциях, а в том, что у вас отсутствует обход вашего файла.
     
Загрузка...

Поделиться этой страницей