Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) ТЗ, как результат прямого запроса (число прочтений - 5028 )
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
ТЗ, как результат прямого запроса
29. Октября 2008 :: 09:01
Печать  
Пытаюсь перенести справочник KLADR (162000 записей) из одной базы в другую. В удаленной базе запросом проверяю наличие по каждому элементу текущей базы (обычный запрос по таблице с условием по наименованию). Запрос возвращает ТЗ с ID элемента или пустую таблицу. Если ТЗ пустая, то эл-та нет в удаленной базе - добавляем новый; если не пустая ТЗ, обновляем всю строку по найденному ID. Так вот после обработки около 39000 элементов запрос возвращает значение типа "Число" (вместо "ТаблицаЗначений") и оно равно -1. При этом 1С постоянно увеличивает потребление памяти (сужу по диспетчеру задач). Как можно объяснить такое явление? Как с ним бороться? Я думаю, что проблема заключается в объекте типа ODBCRecordSet, который и осуществляет общение с удаленной базой.
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #1 - 29. Октября 2008 :: 09:05
Печать  
Что то ты не то делаешь. Базы SQL?
  
Наверх
ICQ  
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #2 - 29. Октября 2008 :: 09:19
Печать  
Да. Небольшие справочники обрабатываются верно и быстро, а вот с этим... А что не то?
Вот такая  функция:

Функция ИДЭлементаСправочника(Справочник, ЭлтСпр, ИмяТаб_Спр, Реж="")
     ТипКода                  = Справочник.ТипКода;
     ДлинаКода           = Справочник.ДлинаКода;
     ДлинаНаименования   = Справочник.ДлинаНаименования;
     КонтрольУникальности= Справочник.КонтрольУникальности;
     Владелец                  = Справочник.Владелец;
     СерииКодов               = Справочник.СерииКодов; 
     
     Если Реж="" Тогда
           РежимПоиска = ОпределитьРежимПоискаЭлемента(Справочник);
     Иначе
           РежимПоиска = Реж;
     КонецЕсли;
     
     ТекстЗапроса = "SELECT Tab1.ID AS ID FROM " + ИмяТаб_Спр + " AS Tab1 (NOLOCK) ";
     
     //Если (СерииКодов = "ВПределахПодчинения") и (Справочник.КоличествоУровней>1) Тогда
     Если ((СерииКодов = "ВПределахПодчинения") и (РежимПоиска = "Код") и (Справочник.КоличествоУровней>1)) или
                 ((Справочник.КоличествоУровней>1) и (РежимПоиска = "Имя")) Тогда
           КонтрРодителя = 1;
     Иначе      
           КонтрРодителя = 0;
     КонецЕсли;
     
     ДлинаПараметра   = 0;
     ТипSQLПараметра  = 14; 
     
     Если ЭлтСпр.ЭтоГруппа() = 1 Тогда
           ЭтоГруппа = "1";
     Иначе
           ЭтоГруппа = "2";
     КонецЕсли;
     
     Если РежимПоиска = "Код" Тогда
           СтрУсловия = "WHERE (Tab1.Code = ?)";
           ДлинаПараметра  = ДлинаКода;
           
           Если ВРЕГ(СокрЛП(ТипКода)) = "ТЕКСТОВЫЙ" Тогда
                 ТипSQLПараметра  = 14;
                 ЗначПарам1  = СокрЛП(Строка(ЭлтСпр.Код));
           Иначе      
                 ТипSQLПараметра  = 4;
                 ЗначПарам1  = Число(ЭлтСпр.Код);
           КонецЕсли;
           
     Иначе
           СтрУсловия = "WHERE (Tab1.Descr = ?)";
           ЗначПарам1     = СокрЛП(ЭлтСпр.Наименование); 
           ДлинаПараметра = ДлинаНаименования;
     КонецЕсли; 
        
     ЗначПарам2 = "";
     Если Владелец.Выбран() = 1 Тогда 
           ИмяТаб_Спр_Влад  = РС.МД.ИмяТаблицыСправочника(Владелец.Идентификатор);
           ТипКодаВладельца = Владелец.ТипКода;
           РежимПоискаВлад  = ОпределитьРежимПоискаЭлемента(Владелец);
           
           Если РежимПоискаВлад = "Код" Тогда
                 ТекстЗапроса = ТекстЗапроса + "INNER JOIN " + ИмяТаб_Спр_Влад + " AS TabOwn (NOLOCK) ON (TabOwn.ID=Tab1.PARENTEXT) ";
                 СтрУсловия   = СтрУсловия + " AND (TabOwn.Code = ?) ";
                 ДлинаПараметра2 = Владелец.ДлинаКода;   
                 
                 Если ТипКодаВладельца = "Текстовый" Тогда
                       ЗначПарам2  = Строка(ЭлтСпр.Владелец.Код);
                       ТипSQLПараметра2  = 14;
                 Иначе      
                       ЗначПарам2  = Число(ЭлтСпр.Владелец.Код);
                       ТипSQLПараметра2  = 4;
                 КонецЕсли;
                 
           Иначе                                          
                 ТекстЗапроса = ТекстЗапроса + "INNER JOIN " + ИмяТаб_Спр_Влад + " AS TabOwn (NOLOCK) ON (TabOwn.ID=Tab1.PARENTEXT) ";
                 СтрУсловия   = СтрУсловия + " AND (TabOwn.Descr = ?) ";
             ЗначПарам2  = СокрЛП(ЭлтСпр.Владелец.Наименование); 
                 ТипSQLПараметра2  = 14;
                 ДлинаПараметра2 = Владелец.ДлинаНаименования;
           КонецЕсли;   
     КонецЕсли;
     
     ЗначПарам3 = "";
     Если КонтрРодителя = 1 Тогда   
           
           Если (ПустоеЗначение(ЭлтСпр.Родитель.Код)=1) и (ПустоеЗначение(ЭлтСпр.Родитель.Наименование)=1) Тогда
                 СтрУсловия = СтрУсловия + " AND (Tab1.ParentID = '" + ПустойИД() + "') AND (Tab1.IsFolder="+ ЭтоГруппа +") "; 
                 
           Иначе
                 Если РежимПоиска = "Код" Тогда    
                       ТекстЗапроса = ТекстЗапроса + "INNER JOIN " + ИмяТаб_Спр + " AS Tab2 (NOLOCK) ON (Tab2.ID=Tab1.ParentID) " ;
                       СтрУсловия   = СтрУсловия + " and (Tab2.Code=?) AND (Tab1.IsFolder=" + СокрЛП(Строка(ЭтоГруппа)) + ") ";
                       
                       Если ТипКода = "Текстовый" Тогда
                             ЗначПарам3  = Строка(ЭлтСпр.Родитель.Код);
                       Иначе      
                             ЗначПарам3  = Число(ЭлтСпр.Родитель.Код);
                       КонецЕсли;    
                       
                 Иначе      
                       ТекстЗапроса = ТекстЗапроса + "INNER JOIN " + ИмяТаб_Спр + " AS Tab2 (NOLOCK) ON (Tab2.ID=Tab1.ParentID) " ;
                       СтрУсловия   = СтрУсловия +  " and (Tab2.Descr=?)AND (Tab1.IsFolder=" + СокрЛП(Строка(ЭтоГруппа)) + ") ";
                       ЗначПарам3   = ЭлтСпр.Родитель.Наименование;
                 КонецЕсли;
                 
           КонецЕсли;
           
     КонецЕсли;
   
     ТекстЗапроса = ТекстЗапроса + СтрУсловия; 
           
     РС.УдалитьПараметры();
     РС.Подготовить(ТекстЗапроса);
     РС.ДобПараметр(1, ТипSQLПараметра, ДлинаПараметра, 0, 0);
     РС.УстПараметр(1, ЗначПарам1); 
     
     Если пустоеЗначение(ЗначПарам2)=0 Тогда
           РС.ДобПараметр(1, ТипSQLПараметра2, ДлинаПараметра2, 0, 0);
           РС.УстПараметр(2, ЗначПарам2);
     КонецЕсли;                         
     
     Если пустоеЗначение(ЗначПарам3)=0 Тогда
           РС.ДобПараметр(1, ТипSQLПараметра, ДлинаПараметра, 0, 0);
           РС.УстПараметр(РС.КолвоПараметров(), ЗначПарам3);
     КонецЕсли;
     
     //РС.Отладка(0);       

     ВремТЗ = РС.ВыполнитьИнструкцию(ТекстЗапроса);
     //РС.ВыполнитьИнструкцию(ТекстЗапроса, ВремТЗ, 1);
     
     Если ПустоеЗначение(ВремТЗ) = 0 Тогда
           Если ТипЗначенияСтр(ВремТЗ) = "ТаблицаЗначений" Тогда
                 ВремТЗ.ВыбратьСтроки();
                 Если ВремТЗ.ПолучитьСтроку()=1 Тогда
                       ИД        = ВремТЗ.ID;
                 КонецЕсли;
           Иначе
                 ИД = "";
                 сообщить(ВремТЗ);
           КонецЕсли;
     Иначе
           ИД = "";
     КонецЕсли;
     //ВремТЗ             = ПолучитьПустоеЗначение();
     ТекстЗапроса = ПолучитьПустоеЗначение();
     СтрУсловия   = ПолучитьПустоеЗначение();
     
     возврат ИД;
КонецФункции
Причем я уже начал обнулять используемые переменные - ничего не помогает. После определенного количества запросов ODBCRecordSet возвращает число вместо ТЗ.
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #3 - 29. Октября 2008 :: 09:28
Печать  
Если у тебя обе справочника в SQL базах то перенос элементов из одной в другую это 2 запроса - 1 Update (для измененных) и 1 Insert (для новых). SQL предназначен для групповой обработки масивов данных, так его использовать как ты это варварство. Это как ты заметил очень долго работает + ещё и с ошибкой вылетает - видимо просто никто такое количество запростов не делал за раз  Смех
  
Наверх
ICQ  
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #4 - 29. Октября 2008 :: 09:31
Печать  
Нельзя одним запросом получить все недостающие элементы?
  
Наверх
ICQ  
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #5 - 29. Октября 2008 :: 10:01
Печать  
Nick писал(а) 29. Октября 2008 :: 09:28:
Если у тебя обе справочника в SQL базах то перенос элементов из одной в другую это 2 запроса - 1 Update (для измененных) и 1 Insert (для новых). SQL предназначен для групповой обработки масивов данных, так его использовать как ты это варварство. Это как ты заметил очень долго работает + ещё и с ошибкой вылетает - видимо просто никто такое количество запростов не делал за раз  Смех

Не спорю - варварство. Я хотел сделать перенос ЛЮБОГО справочника (ВСЕХ его реквизитов) из одной базы в другую. Я этот механизм реализовал - все работает отлично.  Но есть такие ограничения...
И не совсем медленно, кстати. Я предполагал в дальнейшем большую часть работы переложить на сам SQL-сервер, а,  как начало, реализовал таким образом. Обработка происходит поэлементно, потому как у разных элементов одного справочника реквизиты (типа справочник) могут как присутствовать уже в базе-получателе (тогда нужно их просто выбрать), так и отсутствовать (тогда все сложнее и их нужно сначала туда добавить, а затем выбрать)! А если учесть, что в поле хранится только ID элемента справочника, то вид справочника (и соотв. таблицу с данными) можно определить только по метаданным. А перечисления, счета, неопределенные типы? Тот алгоритм, что я реализовал, вполне все корректно выполняет! Справочников такого объема в системе очень немного. Даже если количество элементов в них будет до 30000. Большие объемы имеют всякого рода классификаторы. Они грузятся и стандартными средствами. Я же хотел попробовать свою обработку в таком действии. И к тому же, справочник KLADR отсутствует в стандартной бухгалтерии, поэтому обработки, его загружающей, нет. Можно из ЗиКа выдернуть (что я и сделал сейчас), но я хотел проще.Улыбка
  
Наверх
 
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #6 - 29. Октября 2008 :: 10:05
Печать  
видимо просто никто такое количество запростов не делал за раз

Вот это, я думаю, соответствует истине! Улыбка Где-то в объекте после каждого запроса не реализован сброс (или очистка), поэтому растет потребление оперативки и в конце концов он (ODBCRecordSet) "падает".
  
Наверх
 
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #7 - 29. Октября 2008 :: 10:10
Печать  
Nick писал(а) 29. Октября 2008 :: 09:31:
Нельзя одним запросом получить все недостающие элементы?

Каким образом, например? Если уровень вложенности в реквизите типа "Справочник" может быть большим и, по моему видению вопроса, элементы следующих уровней тоже должны быть перенесены в удаленную базу? Иначе после переноса нужно ручками править. А если переносятся десятки и сотни элементов и в несколько баз? А у какого-то элемента не перенесен, например, реквизит "Ставка налога"  - элемент другого справочника, потому что этого элемента в том справочнике нет и т.д. Может, я и заблуждаюсь! Улыбка
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #8 - 29. Октября 2008 :: 10:13
Печать  
Antes писал(а) 29. Октября 2008 :: 10:05:
видимо просто никто такое количество запростов не делал за раз

Вот это, я думаю, соответствует истине! Улыбка Где-то в объекте после каждого запроса не реализован сброс (или очистка), поэтому растет потребление оперативки и в конце концов он (ODBCRecordSet) "падает".


Нарисуй тест в котором видна утечка памяти, если получится будет тема для разговора с разработчиками.
  
Наверх
ICQ  
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #9 - 29. Октября 2008 :: 10:17
Печать  
Antes писал(а) 29. Октября 2008 :: 10:10:
Nick писал(а) 29. Октября 2008 :: 09:31:
Нельзя одним запросом получить все недостающие элементы?

Каким образом, например? Если уровень вложенности в реквизите типа "Справочник" может быть большим и, по моему видению вопроса, элементы следующих уровней тоже должны быть перенесены в удаленную базу? Иначе после переноса нужно ручками править. А если переносятся десятки и сотни элементов и в несколько баз? А у какого-то элемента не перенесен, например, реквизит "Ставка налога"  - элемент другого справочника, потому что этого элемента в том справочнике нет и т.д. Может, я и заблуждаюсь! Улыбка


Ты ведь можешь на основе метаданных динамически строить запрос, не спорю это будет сложнее, но никто не обещал что будет просто Улыбка
  
Наверх
ICQ  
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #10 - 29. Октября 2008 :: 10:21
Печать  
Nick писал(а) 29. Октября 2008 :: 10:17:
Antes писал(а) 29. Октября 2008 :: 10:10:
Nick писал(а) 29. Октября 2008 :: 09:31:
Нельзя одним запросом получить все недостающие элементы?

Каким образом, например? Если уровень вложенности в реквизите типа "Справочник" может быть большим и, по моему видению вопроса, элементы следующих уровней тоже должны быть перенесены в удаленную базу? Иначе после переноса нужно ручками править. А если переносятся десятки и сотни элементов и в несколько баз? А у какого-то элемента не перенесен, например, реквизит "Ставка налога"  - элемент другого справочника, потому что этого элемента в том справочнике нет и т.д. Может, я и заблуждаюсь! Улыбка


Ты ведь можешь на основе метаданных динамически строить запрос, не спорю это будет сложнее, но никто не обещал что будет просто Улыбка

Каким образом?
Приведенная мной функция тоже формирует запрос в зависимости от структуры того справочника, к которому идет запрос. И тоже на основе метаданных.
  
Наверх
 
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #11 - 29. Октября 2008 :: 10:28
Печать  
видимо просто никто такое количество запростов не делал за раз Улыбка

Так вот как раз на таких экспериментах, как мой, и выявляются как можно больше глюков! Подмигивание
Не было бы такого ограничения, меня все устраивает. И по времени вполне приемлемо! Улыбка
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #12 - 29. Октября 2008 :: 10:35
Печать  
Ну например так:

1. Получаешь все элементы справочника которых нет в другой базе
(результат запроса помещаешь во временную таб SQL)

2. Для каждого реквизита справочника имеющий тип справочник идем к пункту 1.
- После этого у тебя во временных таблицах все не достающие элементы, для всех связаных справочников

3. перенести элементы по ид из временных таблиц в раб. базу в обратном порядке, т.е. сначала подчиненные потом владельцев


Вот как то так, в общих чертах так сказать

  
Наверх
ICQ  
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ТЗ, как результат прямого запроса
Ответ #13 - 29. Октября 2008 :: 10:36
Печать  
Antes писал(а) 29. Октября 2008 :: 10:28:
видимо просто никто такое количество запростов не делал за раз Улыбка

Так вот как раз на таких экспериментах, как мой, и выявляются как можно больше глюков! Подмигивание
Не было бы такого ограничения, меня все устраивает. И по времени вполне приемлимо! Улыбка


И какое время выполнения?
  
Наверх
ICQ  
IP записан
 
Antes
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 57
Зарегистрирован: 17. Октября 2008
Re: ТЗ, как результат прямого запроса
Ответ #14 - 29. Октября 2008 :: 10:43
Печать  
Nick писал(а) 29. Октября 2008 :: 10:35:
Ну например так:

1. Получаешь все элементы справочника которых нет в другой базе
(результат запроса помещаешь во временную таб SQL)

2. Для каждого реквизита справочника имеющий тип справочник идем к пункту 1.
- После этого у тебя во временных таблицах все не достающие элементы, для всех связаных справочников

3. перенести элементы по ид из временных таблиц в раб. базу в обратном порядке, т.е. сначала подчиненные потом владельцев


Вот как то так, в общих чертах так сказать



Спасибо, подумаю.

А время? В одной базе не было справочника "Общероссийский классификатор ОС". Моя обработка переносит его из одной базы в другую ровно за 5 мин. (11000 записей), стандартная загрузка от 1С из текстовика это делает за 11 минут, а перенос через OLE (в инете качал обработку, переносит из удаленой базы в текущую) делает это за 22 минуты. Вот такие результаты. Это то, с чем сталкивался практически только. Вот не вышло сравнить скорость загрузки из dbf KLADR'а и переносом из базы в базу. А хотелось бы. Улыбка
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать