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

Тема в разделе "1C и всё что с ней связано", создана пользователем BBDragon, 6 июл 2010.

  1. BBDragon

    BBDragon Well-Known Member

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

    Код ( (Unknown Language)):
    Процедура ВыборФайла()
    КаталогЗагрузки = "";
    ФайлЗагрузки = "";
    Если ФС.ВыбратьФайл(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 Гость

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

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

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

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

    vbs Well-Known Member

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

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

    Hryv Гость

    согласен на счет транзакций
     
  5. BBDragon

    BBDragon Well-Known Member

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

    vbs Well-Known Member

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

    BBDragon Well-Known Member

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

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

    vbs Well-Known Member

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

    Hryv Гость

    а если 10000 раз по 10? :)
     
  10. vbs

    vbs Well-Known Member

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

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

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

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

    vbs Well-Known Member

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

    BBDragon Well-Known Member

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

    vbs Well-Known Member

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

    BBDragon Well-Known Member

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

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

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

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

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

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

    Регистрация:
    2 апр 2004
    Сообщения:
    2.070
    Симпатии:
    0
    Код ( (Unknown Language)):
    КоличествоЗаписей = 0;
    Пока ... Цикл
    Если КоличествоЗаписей = 0 Тогда
    НачатьТранзакцию();
    КонецЕсли;
    //что-то делаем

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

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

    TimeDontWait Well-Known Member

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

    BBDragon Well-Known Member

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

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

    TimeDontWait Well-Known Member

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

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

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

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