Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника (число прочтений - 4608 )
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
14. Мая 2009 :: 17:06
Печать  
Всем Ку!

1С7.70.025, DBF, 1C++ 3.01.19, FormEx 2.0.5.93

Предыстория: была поставлена задача загрузить ~19000 номенклатурных позиций из экселя в базу. При попытке решения задачи штатными методами столкнулся с проблемой непонятного стремительного роста индексного файла таблицы номенклатуры (на этапе 40% файл занимал больше 1ГБ!). При этом сама скорость загрузки экспоненциально падала. Стоит отметить что помимо самой номенклатуры загружались данные еще в 4 подчиненных справочника: единицы, цены, цены поставщиков, остатки на складах поставщиков. Саму операцию все-же удалось завершить в 3 подхода между которыми удалялись и восстанавливались индексные файлы. В итоге было затрачено около 8 часов. Попытка выяснить причины и возможные пути решения привели к мысли создания механизма записи данных напрямую с помощью средств 1С++. В результате, дабы изучить технологии ООП Улыбка был создан класс, позволяющий осуществлять эту самую операцию.
С применением созданного класса поставленная задача была решена за 12 минут! Правда остался один побочный эффект: индексы все-равно получаются покореженными и справочники ведут себя неадекватно ,) т.е. после загрузки данных необходима переиндексация.

Косяки и вопросы знатокам:
Сам класс доработан только до необходимого уровня для решения поставленной задачи, но при этом содержит несколько явных косяков.
Если справочник имеет реквизит типа "Дата" и для него не передается или передается пустое значение, оно заменяется на дату 01.01.1980, поскольку драйвер матерится и не принимает ни одну из комбинаций:
Код
Выбрать все
гЗапрос.ДобПараметр(1,8,0,0);
гЗапрос.УстПараметр(1,Дата(0));
гЗапрос.УстПараметр(1,'00.00.00');
гЗапрос.УстПараметр(1,'  .  .  ');
гЗапрос.УстПараметр(1,'  /  /    ');
...

гЗапрос.ДобПараметр(1,14,10,0);
гЗапрос.УстПараметр(1,"00/00/0000");
гЗапрос.УстПараметр(1,"00-00-0000");
...
 



Вобщем никак у меня не получилось передать ему пустую дату ,(
Что я делаю не так? Вариант ВыполнитьSQL_ИзТЗ и прочие альтернативные конструкции не пробовал, поскольку мне удобнее использовать конструкцию:
Код
Выбрать все
Запрос.Подготовить(ТекстЗапроса);
Запрос.ДобПараметр(...);
Запрос.УстПараметр(...);
Запрос.ВыполнитьИнструкцию();
 




Ну и просто недоработки:
а) Длинная периодическая строка урезается до 23 символов на одну секцию (мне пока не надо было)
б) Если код справочника имеет строковую составляющую, то новый код скорее всего получить не удастся
в) не учитываются неопределенные ссылки, т.е. 13 символьные, только полностью типизированные объекты С9


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

Спасибо за внимание!
  

________________.rar ( 30 KB | Загрузки )
Наверх
 
IP записан
 
JohnyDeath
1c++ power user
1c++ donor
Отсутствует



Сообщений: 3050
Местоположение: Волгоград
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #1 - 14. Мая 2009 :: 17:46
Печать  
По поводу пустой даты: http://www.1cpp.ru/forum/YaBB.pl?num=1203504717
Если лень читать, то пустая дата в VFP == {^0000-00-00}
  
Наверх
 
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #2 - 14. Мая 2009 :: 18:32
Печать  
Uncle, Покажи код стандартной загрузки и структуру справочника номенклатура с указанием признаков отбора и сортировки. Я считаю что 19000 это совсем не много Подмигивание
  
Наверх
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #3 - 14. Мая 2009 :: 19:15
Печать  
JohnyDeath писал(а) 14. Мая 2009 :: 17:46:
По поводу пустой даты: http://www.1cpp.ru/forum/YaBB.pl?num=1203504717
Если лень читать, то пустая дата в VFP == {^0000-00-00}


Я это читал, и затруднение у меня не в том как использовать пустую дату в запросе, а как ее передать в качестве параметра?
Запрос.УстПараметр("{^0000-00-00}") не работает, для 8 говорит несовместимость типов, для 14 ругается ... что-то типа на размер, точно не помню.

  
Наверх
 
IP записан
 
Donat
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 152
Зарегистрирован: 29. Мая 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #4 - 14. Мая 2009 :: 19:22
Печать  
А почему используется ODBC а не OLEDB? Последнее, вроде, более работоспособное.
  
Наверх
 
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #5 - 14. Мая 2009 :: 19:38
Печать  
Donat писал(а) 14. Мая 2009 :: 19:22:
А почему используется ODBC а не OLEDB? Последнее, вроде, более работоспособное.

Да как-то по привычке, можно будет пожже переписать под олю и сравнить производительность
  
Наверх
 
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #6 - 14. Мая 2009 :: 19:40
Печать  
leshik писал(а) 14. Мая 2009 :: 18:32:
Uncle, Покажи код стандартной загрузки и структуру справочника номенклатура с указанием признаков отбора и сортировки. Я считаю что 19000 это совсем не много Подмигивание

Завтра покажу, на работе все осталось, хотя в коде ничего необычного нету
  
Наверх
 
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы с
Ответ #7 - 15. Мая 2009 :: 05:09
Печать  
2 leshik

Вот функция создания нового элемента справочника, структуру смотри в аттаче
Код
Выбрать все
Функция ПолучитьЭлемент(К,Н="")
	Кво = гСпрНом.НайтиПоРеквизиту("Артикул",К,1);
	Если Кво=0 Тогда
		Если ПрямойДоступ=1 Тогда
			гПсНом.Наименование = глУбратьНепечСимв(Н);

			гПсНом.Установить(гПсНом.Наименование,"ПолнНаименование");
			гПсНом.Установить(ВалютаУчета,"ВалютаУчета");
			гПсНом.Установить(глУбратьНепечСимв(К),"Артикул");
			гПсНом.Установить(Константа.ТипБазовойЕдиницыПоУмолчанию,"БазоваяЕдиница");
			гПсНом.Установить(Константа.ОсновнаяСтавкаНДС,"СтавкаНДС");
			гПсНом.Установить(Перечисление.ВидыТоваров.Товар,"ВидТовара");
			гПсНом.Установить(Перечисление.ТипыТоваров.Штучный,"ТипТовара");
			Если ПустоеЗначение(гПсНом.Код)=0 Тогда
				гПсНом.Код = гПсНом.Код + 1;
			КонецЕсли;

			гСпрНом.НайтиЭлемент(гПсНом.СоздатьЭлемент());
		Иначе
			гСпрНом.ИспользоватьРодителя(ГруппаСправочника);
			гСпрНом.Новый();
			гСпрНом.Артикул = глУбратьНепечСимв(К);
			гСпрНом.Наименование = глУбратьНепечСимв(Н);
			гСпрНом.ПолнНаименование = гСпрНом.Наименование;
			гСпрНом.ВалютаУчета=ВалютаУчета;
			гСпрНом.БазоваяЕдиница=Константа.ТипБазовойЕдиницыПоУмолчанию;
			гСпрНом.СтавкаНДС=Константа.ОсновнаяСтавкаНДС;
			гСпрНом.ВидТовара=Перечисление.ВидыТоваров.Товар;
			гСпрНом.ТипТовара=Перечисление.ТипыТоваров.Штучный;
			гСпрНом.ИспользоватьДату('01.01.1980');
			Попытка
				гСпрНом.Записать();
			Исключение
				Сообщить(ОписаниеОшибки());
				Возврат 0;
			КонецПопытки;
		КонецЕсли;
	КонецЕсли;

	Если гСпрНом.ПометкаУдаления()=1 Тогда
		гСпрНом.СнятьПометкуУдаления();
	КонецЕсли;

	Возврат гСпрНом.ТекущийЭлемент();
КонецФункции
 



Функция глУбратьНепечСимв() убирает непечатные символы, кот. могут прийти из екселя
  

_________.txt ( 13 KB | Загрузки )
Наверх
 
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #8 - 15. Мая 2009 :: 05:41
Печать  
1) Константа.ТипБазовойЕдиницыПоУмолчанию и т.д. вынеси в переменные чтобы не считывать постоянно из базы;
2) Я думаю что создание не обернуто в транзакцию - оберни в транзакцию по 10-30 элементов;
3) Покажи код функции глУбратьНепечСимв(Н); Я думаю что там ты используешь что-то типа
Для Сч = 1 По СтрДлина(Н)
А на самом деле СтрДлина(Н) можно вынести перед циклом;
4) гСпрНом.ИспользоватьДату('01.01.1980') вынеси вообще за функцию - эту инструкцию можно применить 1 раз;
5) Зачем обернуто в попытку? Бывает что и не записывается? Транзакция и Попытка вместе не использовать.
Я уверен что твой СТАНДАРТНЫЙ код можно привести к состоянию оочень быстрой загрузки.
Замедление к концу связано с перестроением индексов по реквизитам:
Идентификатор      "Артикул"
                 - Синоним      "Артикул"
                 - Тип      "Строка"
                 - Длина      "30"
                 - Сортировка      "1"
                 - Отбор      "1"
Идентификатор      "ШтрихКод"
                 - Тип      "Число"
                 - Длина      "13"
                 - Сортировка      "1"
                 - Отбор      "0"
Идентификатор      "КодТов"
                 - Тип      "Строка"
                 - Длина      "25"
                 - Сортировка      "1"
                 - Отбор      "0"
Идентификатор      "ВнешнийКод"
                 - Тип      "Число"
                 - Длина      "10"
                 - Сортировка      "1"
                 - Отбор      "1"
Посмотри а правильно ли задана длина реквизитов? Возможно в полях хранится менее длинное содержимое и длину поля можно уменьшить;
Подумай, а везде ли нужен Отбор (это все таки дополнительный индекс). Обычно достаточно бывает Сортировки.
  
Наверх
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #9 - 15. Мая 2009 :: 06:10
Печать  
2 leshik
Спасибо, учту замечания, сравню производительность и покажу результаты...

leshik писал(а) 15. Мая 2009 :: 05:41:
1)
Замедление к концу связано с перестроением индексов по реквизитам:
Идентификатор      "Артикул"
                 - Синоним      "Артикул"
                 - Тип      "Строка"
                 - Длина      "30"
                 - Сортировка      "1"
                 - Отбор      "1"
Идентификатор      "ШтрихКод"
                 - Тип      "Число"
                 - Длина      "13"
                 - Сортировка      "1"
                 - Отбор      "0"
Идентификатор      "КодТов"
                 - Тип      "Строка"
                 - Длина      "25"
                 - Сортировка      "1"
                 - Отбор      "0"
Идентификатор      "ВнешнийКод"
                 - Тип      "Число"
                 - Длина      "10"
                 - Сортировка      "1"
                 - Отбор      "1"
Посмотри а правильно ли задана длина реквизитов? Возможно в полях хранится менее длинное содержимое и длину поля можно уменьшить;
Подумай, а везде ли нужен Отбор (это все таки дополнительный индекс). Обычно достаточно бывает Сортировки.


подумаю что тут можно сделать, может ты и прав насчет отбора
  
Наверх
 
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #10 - 15. Мая 2009 :: 11:22
Печать  
Поторопился ответить, надеюсь никто не успел прочесть тот пост что я сейчас удалил ,))
Так вот, с учетом рекомендаций leshik'a удалось добиться нормальной равномерной и быстрой загрузки всего справочника с нормальной динамикой роста индексного файла. В итоге штатным способом загрузка завершилась за 7:20 мин. С помощью прямого справочника 12 мин. Вот теперь думаю неужели все-таки штатным способом быстрее или у меня просто неоптимизированный класс.....
  
Наверх
 
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #11 - 15. Мая 2009 :: 11:24
Печать  
Цитата:
7:20 мин

долговато  Подмигивание
покажи все таки функцию про непечатаемые символы?
  
Наверх
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #12 - 15. Мая 2009 :: 11:28
Печать  
leshik писал(а) 15. Мая 2009 :: 11:24:
Цитата:
7:20 мин

долговато  Подмигивание
покажи все таки функцию про непечатаемые символы?


Код
Выбрать все
глНеПечатаемыеСимволы = СоздатьОбъект("СписокЗначений");
Для Сч=0 По 31 Цикл
	глНеПечатаемыеСимволы.ДобавитьЗначение(Симв(Сч));
КонецЦикла;


Функция глУбратьНепечСимв(Стр) Экспорт
	Стр_ = "";
	Длина = СтрДлина(Стр);
	Для Сч=1 По Длина Цикл
		Смв = Сред(Стр,Сч,1);
		Если глНеПечатаемыеСимволы.Принадлежит(Смв)=0 Тогда
			Стр_=Стр_+Смв;
		КонецЕсли;
	КонецЦикла;

	Возврат Стр_;
КонецФункции
 

  
Наверх
 
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #13 - 15. Мая 2009 :: 11:33
Печать  
Код
Выбрать все
глНеПечатаемыеСимволы ="";
Для Сч=0 По 31 Цикл
	глНеПечатаемыеСимволы = глНеПечатаемыеСимволы+Симв(Сч);
КонецЦикла;


Функция глУбратьНепечСимв(Стр) Экспорт
	Стр_ = "";
	Длина = СтрДлина(Стр);
	Для Сч=1 По Длина Цикл
		Смв = Сред(Стр,Сч,1);
		Если Найти(глНеПечатаемыеСимволы,Смв)=0 Тогда
			Стр_=Стр_+Смв;
		КонецЕсли;
	КонецЦикла;

	Возврат Стр_;
КонецФункции
 


Я думаю что будет быстрее.
Это если стандартно - а не стандартно - можно было бы ИтТз сделать с индексом по одной колонке и в ней искать. Ну или Структуру задействовать.
А также интересно откуда считываешь? - может покажешь откуда считываешь?
  
Наверх
IP записан
 
Uncle
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 93
Зарегистрирован: 26. Июля 2006
Re: Класс "ПрямойСправочник": позволяет напрямую создавать элементы справочника
Ответ #14 - 15. Мая 2009 :: 11:41
Печать  
leshik писал(а) 15. Мая 2009 :: 11:33:
[code]глНеПечатаемыеСимволы ="";
...
Я думаю что будет быстрее.
Это если стандартно - а не стандартно - можно было бы ИтТз сделать с индексом по одной колонке и в ней искать. Ну или Структуру задействовать.
А также интересно откуда считываешь? - может покажешь откуда считываешь?


Спасибо, попробую, но вообще-то в замере производительности эта операция итак занимает весьма скромную позицию. В аттаче вся обработка
  

______________.rar ( 21 KB | Загрузки )
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать