Имя: Пароль:
1C
1С v8
Подскажите с записью в MS SQL
0 Garkin
 
07.05.13
22:37
Есть рабочая процедурка записи таблицы контрагентов в SQL

Процедура ДобавитьКонтрагентов(Тз);
   
   Recordset = Новый COMObject("ADODB.RecordSet");
   Recordset.ActiveConnection=Connection;

   ТекстЗапроса= "SELECT * FROM customer";
   
   Recordset.CursorType=3;
   Recordset.LockType=3;
   Recordset.Open(ТекстЗапроса);

   БезПоиска=Ложь;
   Если Recordset.BOF=Истина Тогда
       БезПоиска=Истина;
   КонецЕсли;    
    Нпп=0;
    Для Каждого Тс Из Тз Цикл
        Нпп=Нпп+1;
        Состояние("Контрагенты "+Нпп);
       Если ЗначениеЗаполнено(Тс.Контрагент) = Ложь Тогда
            Тс.Контрагент=Справочники.Контрагенты.ПустаяСсылка();
       КонецЕсли;    
           
       Если БезПоиска=Истина Тогда
           Recordset.AddNew();
       Иначе    
           Если Recordset.BOF=Ложь Тогда
               Recordset.MoveFirst();
               Recordset.Find("id_customer='" +Тс.Контрагент.Код + "'");
           КонецЕсли;    
           Если Recordset.EOF=Истина Тогда
               Recordset.AddNew();
           КонецЕсли;    
       КонецЕсли;    
       
       Recordset.Fields("id_customer").Value = Тс.Контрагент.Код;
       Recordset.Fields("name_customer").Value = Лев(СокрЛП(Тс.Контрагент.Наименование),100);
       Recordset.Fields("id_grp").Value = Тс.Контрагент.Родитель.Код;
       Recordset.Fields("unn").Value = Лев(СокрЛП(Тс.Контрагент.УНП),9);
       Если ЗначениеЗаполнено(Тс.Район) Тогда
           Recordset.Fields("id_raj").Value =Тс.Район.Код;
       КонецЕСли;    
       Recordset.Fields("id_sales").Value = Тс.СотрудникКод;
       Recordset.Update();
       
   КонецЦикла;    
   
   Recordset.Close();

КонецПроцедуры
 
Работала с Postgre достаточно шустро, перевели на MS SQL  жутко тормозит вот в этом месте:
Recordset.Find("id_customer='" +Тс.Контрагент.Код + "'");

Подскажите где что пнуть чтобы ускорить?
1 sda553
 
07.05.13
22:47
(0) пнуть замер производительности в конфигураторе и сказать в каких строках этой портянки он наибольший
2 Garkin
 
07.05.13
22:49
(1) вот здесь
Recordset.Find("id_customer='" +Тс.Контрагент.Код + "'");
3 sda553
 
07.05.13
22:51
(2) Я бы вообще не использовал find, кол надо переделать. Если малой кровью, то seek надо использовать
4 MaxS
 
07.05.13
22:52
(2) зачем нужен SQL сервер, если используется такая конструкция - поиск в цикле по одной строке?

Нужно оптимизировать и искать одним запросов всё.
5 sda553
 
07.05.13
22:53
тут наоборот надо обходить recordset в цикле, а искать в тз
6 sda553
 
07.05.13
22:54
(5) не читать, это я глупость сказал.
Обходим так же тз и на каждую строку делаем запрос с where
7 MaxS
 
07.05.13
22:54
И это можно оптимизировать и выводить каждое 100-е, например.  Состояние("Контрагенты "+Нпп);
8 MaxS
 
07.05.13
23:11
Максимальная скорость будет, если предварительно подготовить список кодов из 1С и одним запросом у SQL узнать наличие контрагентов.  Получить в 1С массив существующих на SQL контрагентов.

Из Тз, к котором есть контрагенты и из массива существующих, нужно получить результат запроса с информацией о всех контрагентах, которых нет в SQL. Вместо Тс.Контрагент.Код использовать ВыборкаДетальныеЗаписи.Код. и т.п.
9 Garkin
 
07.05.13
23:26
(3)-(8) спасибо. Но все равно непонятно почему в Постгре это нормально работает, а на MS SQL такие тормоза?
10 timurhv
 
07.05.13
23:31
(9) Пример приведи сколько было элементов в справочнике "Контрагенты" во времена Постгри и сколько сейчас.
11 Garkin
 
07.05.13
23:41
(10) Да одинаково, порядка 1000. В постгре выгружается секунд 20, в MS SQL минут 10.
12 МихаилМ
 
07.05.13
23:45
у Вас перепутана обработка данных с получением и выводом
данных. полный винигрет.



сответственно если Вы хотите управлять
производительностью и надежностью

разбейте метод на 3 метода

1) получение данных из бд
2) обработка данных
3) запись данных    

никогда не используйте * в запросе
в рабочем коде
выбирайте только нужные для обработки поля.
иначе кто-то может добавить поля типа image

*  только для отладки

мыслите множествами, а не строками  
данные выбирайте множеством.
обработку данных делайте множеством
не бойтесь "лишних" циклов
если методов несколько: правильней вызвать метод для каждой
сущности  

чем несколько методов для каждой строки.


сответственно

1)
запросом получите данные в ТЗ
без Тс.Район.Код , Тс.Контрагент.Наименование

2) обработайте до вида пригодго для загрузки в БД

3) загрузите в временную таблицу
  обработайте  данные на пригодность на стороне субд
  результат обработки  в  ВТ ошибок
  выполните обновление
 
получите информацию о результате и обработайте
13 Garkin
 
07.05.13
23:55
(12) Спасибо, т.е. так чтоб ничего не делать не получится :(, жаль.
14 Jaap Vduul
 
07.05.13
23:58
А что ж ты хочешь?
У тебя серверный курсор с оптимистической блокировкой.
Ты своим find кучу телодвижений на сервере вызываешь.
С точки зрения минимальной переделки - замена find на filter
15 Sammo
 
08.05.13
06:01
Имхо, здесь вообще можно обойтись без подобного использования recordset, особенно при количестве в 1000 штук.
Собираем текст со скулевым запросом, где на каждую строку ТЗ делаем select where.
Если его нет, то insert. Если есть и надо все равно - update.
И потом запускаем готовую портянку с полученным запросом.
Command.CommandText = полученный текст запроса.
RecordSet = Command.Execute()
16 sttt
 
08.05.13
06:29
попробуй в транзакции сделать
17 sttt
 
08.05.13
06:31
и Тс.Контрагент.Код получай в самом запросе а не в цикле из тз
18 ЧеловекДуши
 
08.05.13
07:26
Используй "IINSERT INTO table_name
VALUES (value1,value2,value3,...)",
http://www.w3schools.com/sql/sql_insert.asp
с командой по 250 строк. (ну мин 100)
19 ЧеловекДуши
 
08.05.13
07:27
(16) А транзакция чем поможет? :)
20 Karavanych
 
08.05.13
08:12
хм я вообще, я UPDATE и INSERT INTO юзал.

но если ты хочешь дальше использовать курсор,
то я бы выбрал только нужные записи в select + order by id_customer по массиву кодов контрагента, затем  отсортировал твою ТЗ так же по кодам контрагента,
и по порядку перебирал записи - считай find вообще не нужно бы были использовать, потому что у тебя они по порядку обе ТЗ отсортированы одинакого, просто берешь следующую строку и все. (с оговоркой что проверка на существование этих записей в обеих таблицах - сделана,если нет - ничего страшного, просто надо шаг в существующей сделать лишний).
21 sttt
 
08.05.13
08:51
(19) вроде как помогает ускорить.

еще можно журнал транзакций шринк сделать или вставлять записи без журнала
22 sttt
 
08.05.13
08:53
ALTER DATABASE МойБаза SET RECOVERY SIMPLE