Имя: Пароль:
1C
1С v8
Ускорение проведения
,
0 romaku
 
16.08.11
20:24
Есть куча ручных операций. Там нужно заменить один счет на другой.

Цикл по операциям:
Набор = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(Объект.Ссылка);
Набор.Прочитать();
Для каждого Запись из Набор Цикл
   Если Запись.СчетКт = "800" тогда
       Запись.СчетКт = "900" (условно)
   КонецЕсли;
КонецЦикла;
Набор.Записать();
КонецЦикла по операциям.

Все это дело работает очень медленно, операций и проводок очень много. можно как-то ускорить процесс?
1 МихаилМ
 
16.08.11
20:27
про транзакцию почитайте
про не явные преобразоваеия типов
2 romaku
 
16.08.11
20:28
НачатьТРанзакцию() в начале, и ЗафиксироватьТранзакцию() в конце вставил. Все равно долго. Или я что-то не понял как необходимо с ней работать.
А что с преобразованием типов?
3 asady
 
16.08.11
20:29
(0) отключи итоги по РБ
потом выполни все изменения
потом включи итоги
4 KRV
 
16.08.11
20:29
Провести.Быстро.Мля!()
5 romaku
 
16.08.11
20:30
Зада кстати не только замены счета одного на другой, но и одного значения субконто на другое. счет - это для примера.

Можно как-то сделать запрос на обновление данных?
6 Stim213
 
16.08.11
20:36
Для каждого Запись из Набор Цикл - это для новичков.

Тру-программеры обрабатывают в запросе такие вещи и загружают ТЗ в движения. Примерно так:

Запрос = Новый Запрос;
   Запрос.Текст = "ВЫБРАТЬ
   |    ХозрасчетныйДвиженияССубконто.Период,
   |    ХозрасчетныйДвиженияССубконто.НомерСтроки,
   |    ХозрасчетныйДвиженияССубконто.Активность,
   |    ВЫБОР
   |        КОГДА ХозрасчетныйДвиженияССубконто.СчетДт = &Счет                    
   |            ТОГДА &СчетЗаменить
   |        ИНАЧЕ ХозрасчетныйДвиженияССубконто.СчетДт
   |    КОНЕЦ КАК СчетДт

бла-бла

а потом

ТЗЗаписей = Запрос.Выполнить().Выгрузить();
МояОперация.Движения.Хозрасчетный.Загрузить(ТЗЗаписей);
7 Господин ПЖ
 
16.08.11
20:38
>Тру-программеры обрабатывают в запросе

1Ц за запросы в цикле ставит тру-двойки на сертификации...
8 romaku
 
16.08.11
20:42
(6) я новичок.

что такое МояОперация?
Это, я так понял, делается не в цикле, а просто подмена счета или субконто в итоговой таблице запроса происходит? или не так понял?
9 GROOVY
 
16.08.11
20:43
(7) СовсемТруПрограммеры делают запрос, который находит все что надо переделать, и на его основе в цикле по результату запроса в транзакции формируют движения.
10 GROOVY
 
16.08.11
20:44
За (6) можо поставить ну не 2, а 3...
11 romaku
 
16.08.11
20:45
я сделал запрос, который выбирает все что нужно переделать.
выгрузил итог запроса в таблицу.
а дальше по таблице в цикле:
Набор.Отбор.Регистратор.Установить(тз.Объект.Ссылка);
Набор.Прочитать();
Проводка = НаборЗаписей.Получить(тз.НомерСтроки-1);

   Если проводка.СчетКт = "800" тогда
       проводка.СчетКт = "900" (условно)
   КонецЕсли;
КонецЦикла;
Набор.Записать();
КонецЦикла;
12 Stim213
 
16.08.11
20:46
(7)Если бы можно было загружать выборку по итогам в ТЗ, было бы еще здоровее.
А по поводу запросов в цикле - иногда это полезно. Полезнее, например, чем в делать вложенные циклы, как в (0). Да и авторы типовых совсем не брезгуют запросами в цикле
13 GROOVY
 
16.08.11
20:47
(12) Как в (0) делать вообще никогда не надо и это не оправдание запросу в цикле.
14 Stim213
 
16.08.11
20:48
когда операции созданы программно и имеют более 1к строк - то лучше загружать через выборку запроса(ТЗ)
15 GROOVY
 
16.08.11
20:48
(11) Ты чето не понял. Зачем тебе идиотские циклы и условия по результату запроса? Там уже все отобрано должно быть.
16 Stim213
 
16.08.11
20:48
(13)а как по-другому? Имхо - это самый быстрый вариант.
17 romaku
 
16.08.11
20:48
так как надо сделать?
запроса в цикле нет. сперва запрос, потом итог запроса в таблицу, затем обработка таблицу.
затык на том что НаборЗаписей,Записать() очень долго времени занимает.
18 GROOVY
 
16.08.11
20:53
Запрос формирует выборку с полями "Регистратор, номерСтроки, Счета и другие данные о проводке". Выборку попадает только отобранные по условиям проводки. В запросе используются итоги по регистратору.

На основе иерархической выборки запроса формируется 2 цикла. Первый цикл Выбирает регистратор, второй ищет в наборе записей с отбором по регистратору нужную строку и заменяет значение.

По результату внутри цикла по Регистратору происходит запись набора записей.

Над обоими цикла разумно использовать транзакцию со счетчиком фиксирования. Размер записей в транзакции разумно подобрать экспериментально, например за начальное значение может сойти 10000.
19 GROOVY
 
16.08.11
20:55
(16) Иди учиться.
(14) Какая разница как созданы записи в регистре? Обрабатывать ВСЕ строки - бред. Загрузка данных из результата запроса в набор записей не всегда быстрее обработки данных в выборке. Как раз в регистре бухгалтерии это будет медленнее, из-за составного типа субконто.
20 Aleksey
 
16.08.11
20:57
(11) Итоги отключил?
21 Stim213
 
16.08.11
21:00
"Запрос формирует выборку с полями "Регистратор, номерСтроки, Счета и другие данные о проводке". Выборку попадает только отобранные по условиям проводки"

"По результату внутри цикла по Регистратору происходит запись набора записей."

Ловко, однако. Из 100 записей одного регистратора будет отобрано запросом только 2(к примеру) и эти две будут обходиться во втором цикле. И эти две в итоге запишутся в регистр, перезаписывая или добавляясь к предыдущим записям.

(РегистрБухгалтерииНаборЗаписей.<Имя регистра бухгалтерии> (AccountingRegisterRecordSet.<Имя регистра бухгалтерии>)
Записать (Write)
Синтаксис:

Записать(<Замещать>)
Параметры:

<Замещать> (необязательный)

Тип: Булево. Определяет режим замещения существующих записей в соответствии с текущими установками отбора. Истина - перед записью существующие записи будут удалены. Ложь - записи будут дописаны к уже существующим в информационной базе записям.
)
22 Stim213
 
16.08.11
21:01
+ это я СП скопировал, если что
23 GROOVY
 
16.08.11
21:02
(21) Прочитав набор записей и заменив в нем 2 строки Ты предлагаешь ДОПИСАТЬ чтоли второй раз данные в базу?
24 Stim213
 
16.08.11
21:06
(23) выложи плз код, а то я тебя не пойму. Ты хочешь обойти иерархическую выборку запроса и в то же время читать набор записей РБ.
25 artbear
 
16.08.11
21:08
(23) Нафига внутри второго цикла еще раз выполнять поиск?
ИМХО это как раз медленно!
Пояснишь?
ЗЫ у нас уже почти ночь, возможно, я что-то не понял.
26 GROOVY
 
16.08.11
21:11
(24) Код не выложу, нет 1С, писать в блокноте лень.
(25) Поиск по номеру строки в наборе записей очень быстро.
27 Stim213
 
16.08.11
21:13
Набор записей все равно придется записывать полностью. Не важно, что из 100 записей регистратора только одна проводка исправлена - записывать приходится весь набор регистратора, разве нет?
28 GROOVY
 
16.08.11
21:15
(27) Естественно.
29 Stim213
 
16.08.11
21:20
(28)тогда твой метод получается медленнее.
Что быстрее:

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

2. Получаем выборку регистраторов, где есть проводки с нужным счетом
 Цикл - обходим регистраторы
  Вложенный цикл - получаем исправленную ТЗ, без обхода проводок
 КонецЦикла
ЗаписываемНаборЗаписей


В то время, пока ты будешь обходить записи - я получу исправленную ТЗ и загружу её в набор. В вилларибо еще моют посуду, а в вилабаджио поют и танцуют.
30 artbear
 
16.08.11
21:20
(28) ИМХО на повторном чтении набора по регистратору ты упустишь весь выигрыш от запроса :(
31 artbear
 
16.08.11
21:20
(29) ты также не прав :(
32 artbear
 
16.08.11
21:21
(29) Опиши, как во вложенном цикле ты получишь ТЗ ?
через повторный запрос чтоли?
33 vde69
 
16.08.11
21:26
пишу на память (ошибок наверно много), конечно это тоже не оптимально но будет сильно быстрее

начатьтранзакцию()
Набор.Отбор.Регистратор.Установить(тз.Объект.Ссылка);
Набор.Прочитать();
тз=Набор.Выгрузить();
отбор = новый соответствие;
отбор.вставить("СчетКт", 800);
ст = тз.найтистроки(отбор);
для каждого эл из ст цикл
       эл.СчетКт = "900" (условно)
КонецЦикла;
Набор.загрузить(ТЗ);
Набор.Записать();
КонецЦикла;
зафиксироватьтранзакцию()
34 Stim213
 
16.08.11
21:27
(32)да.

Запрос = Новый Запрос;    
   Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
                  |    ХозрасчетныйДвиженияССубконто.Регистратор
                  |ИЗ
                  |    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Счет = &Счет И ХозрасчетныйДвиженияССубконто.Регистратор ССЫЛКА Документ.ОперацияБух, , ) КАК ХозрасчетныйДвиженияССубконто";    
   
   Запрос.УстановитьПараметр("Счет",счетИскать);
   ВыборкаДокументов = Запрос.Выполнить().Выбрать();
   Пока ВыборкаДокументов.Следующий() Цикл
       ТЗЗаписей = ПолучитьИсправленныйНаборЗаписей(ВыборкаДокументов.Регистратор);
       Операция = ВыборкаДокументов.Регистратор.ПолучитьОбъект();
       Операция.Движения.Хозрасчетный.Загрузить(ТЗЗаписей);
Операция.Записать();
КонецЦикла
35 GROOVY
 
16.08.11
21:27
(29) Возьми 1с и затести. Незабудь отписаться о результатах.
(30) Согласен.
36 GROOVY
 
16.08.11
21:28
(34) А нафига тебе ДОКУМЕНТ то читать?
37 artbear
 
16.08.11
21:30
(29) Заново прочитал твое (6)
Да, ты говоришь о запросах внутри цикла.
Совсем не гуд.
Лично я сделал так:
фактически компоную ваши подходы
все исправления делаю сразу в запросе (выбор если счетДт = ХХ ТОГДА &СчетЗаменить Иначе СчетДТ), в нем собираю всю таблицу
и в запросе ставлю итоги по регистратору
внешний цикл по регистратору, внутренний - создаю набор записей из выборки (через простые и быстрые Добавить, ЗаполнитьЗначенияСвойств), после выхода из внутреннего цикла идет запись созданного набора.
38 Stim213
 
16.08.11
21:30
+
Функция  ПолучитьИсправленныйНаборЗаписей(Регистратор)
Запрос = Новый Запрос;
   Запрос.Текст = "ВЫБРАТЬ
   |    ХозрасчетныйДвиженияССубконто.Период,
   |    ХозрасчетныйДвиженияССубконто.НомерСтроки,
   |    ХозрасчетныйДвиженияССубконто.Активность,
   |    ВЫБОР
   |        КОГДА ХозрасчетныйДвиженияССубконто.СчетДт = &Счет
   |    ТОГДА &СчетДобавить
   |        ИНАЧЕ ХозрасчетныйДвиженияССубконто.СчетДт
   |    КОНЕЦ КАК СчетДт,
   |    ХозрасчетныйДвиженияССубконто.СубконтоДт1
   |    ВЫБОР
   |        КОГДА ХозрасчетныйДвиженияССубконто.СчетКт = &Счет
   |            ТОГДА &СчетДобавить
   |        ИНАЧЕ ХозрасчетныйДвиженияССубконто.СчетКт
   |    КОНЕЦ КАК СчетКт,
   |    ХозрасчетныйДвиженияССубконто.СубконтоКт1,
бла-бла

   Запрос.УстановитьПараметр("Счет",счетИскать);
   Запрос.установитьПараметр("Регистратор", Регистратор);
   Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
39 artbear
 
16.08.11
21:32
(33) Тз.Объект.Ссылка сильно выглядит :(
Незачет :)
(36) Прав, нафига документ-то читать, ссылки достаточно.
У тебя и без этого будут потери на запросах :(
Что скажете о моем варианте (37)
40 Stim213
 
16.08.11
21:32
(37) а что гуд - внутри цикла создавать еще один цикл по отобранным проводкам? Запрос быстрее вернет ТЗ, имхо.
41 Stim213
 
16.08.11
21:33
(36) чтобы обратиться к его движениям
42 Stim213
 
16.08.11
21:33
+40 а записывать все равно весь набор записей
43 artbear
 
16.08.11
21:34
Ты попробуй на реальной базе для документов более 200, ИМХО даже на столь малом количестве увидишь потери
Вложенный цикл для такой задачи с потенциально большим количество документов ЗЛО.
44 GROOVY
 
16.08.11
21:34
(39) Да на чтении набора сильно съэкономим, но есть проблема "огромных" движений, хотя это исключение скорее.
(41) Посмотри в (0) как движения редактировать.
45 milan
 
16.08.11
21:34
Правильный ответ был в (3)
46 GROOVY
 
16.08.11
21:35
(40) не прав.
47 Stim213
 
16.08.11
21:36
(46) почему? Выборкой я получаю срез внутренней таблицы, а цикл обходит всяко дольше
48 artbear
 
16.08.11
21:36
(3) Недостаточно
49 GROOVY
 
16.08.11
21:36
(40) Ты учти что сначала ты результат запроса конвертируешь в ТЗ, а потом ТЗ конвертируешь в набор записей. Метод "Загрузить" это не просто встасить ТЗ в ТЗ, а конвертация типов, сопоставление по идентификаторам.
50 artbear
 
16.08.11
21:37
(45) Предложения из (3) Недостаточно
51 GROOVY
 
16.08.11
21:38
Да еще Запрос это такая штука которая требует трянсляции к скулю и пост обработки того что скуль вернул.
52 Stim213
 
16.08.11
21:39
(49)ну.. не вопрос. замерю производительность и отпишусь. Ты только код свой оставь, чтобы было по-честному
53 GROOVY
 
16.08.11
21:40
(52) Мне лень. Начинай ты, потом я свой код выложу. Пишу с нетбука, 1С нет, ставить ради такой ерунды нет желания. Я в командировке, доступа к рабочему компу не будет до конца месяца.
54 milan
 
16.08.11
21:41
(50) зависит, кончено отого, как часто встречается замена счетов. По идее если набор не изменился, в базу писаться он не будет. Автор описал что записать() делается дольше всего?
55 artbear
 
16.08.11
21:44
(53) А как же облачные вычисления ? неужели у тебя доступа к ним нету? ну или банальный терминальный доступ :)
ЗЫ шучу, конечно, задача на самом деле простая.
Но для ваших курсов вполне годная. У разработчик встречается не так уж и редко :)
56 artbear
 
16.08.11
21:46
(54) Набор изменится в любом случае, мы же работаем только с теми регистраторами и наборам, где нужно поменять счета.
57 Fragster
 
гуру
16.08.11
21:46
(0) перед выполнением выключить итоги (рассчитать на дату перед первой заменой, если не весь период заменяется), после выполнения включить обратно.
58 milan
 
16.08.11
21:49
(56) ну и какой смысл тогда выгадывать копейки, если записать ()  съедает большую часть времени работы?
59 artbear
 
16.08.11
21:51
(53) Меня с момента появления Снеговика мучает вопрос:
почему 1С не сделала возможность получения таблицы значений из выборки? Почему РезультатЗапроса.Выгрузить(), а Выборка.Выгрузить() нет ?
ведь очень часто, сабж это только подтверждает, можно было бы быстро получить нужную ТЗ и дальше работать с ней, например, загрузить в набор и т.п.
Т.е. 1С можно было бы продублировать с оптимизацией все действия, которые все равно делает разработчик/пользователь выборки.
ИМХО за счет оптимизации внутри кода 1С подобная задача решалась бы быстрее :)
60 artbear
 
16.08.11
21:54
(58) 1. Автор об этом не писал :)
2. Записать не обязательно очень долго будет!
на "плохих" запросах Записать как раз не так сильно будет влиять :)
3. На Записать повлиять можно с трудом, а вот на запросы вполне в наших силах.
61 Stim213
 
16.08.11
21:55
(59)да. да-да. Это косяк(
62 milan
 
16.08.11
22:01
(60) в (17) писал
в снеговике здорово ускорили исполнение кода. Сам всегда формирую таблицу движений в запросе, но на скорость проведения на 90% влияет чтение и запись данных, так что выигрыш от таких манипуляций никакой.
63 artbear
 
16.08.11
22:08
(62) Конечно, нужно смотреть замеры производительности.
Но учитываем все сказанное всеми нами + тот факт, что автор еще неопытный, так что слишком большого доверия его словам нельзя придавать :(
Тем более, что интересная и не столь уж редкая задача :)
64 Dmitrii
 
гуру
16.08.11
22:22
Ускорение при выполнении записи набора будет только при отключении итогов и актуальных итогов регистра.

Заполнение набора из ТЗ для регистра бухгалтерии будет медленнее, чем, например, для регистра накопления, из-за того, что для него не соблюдается порядок следования субконто на счете, а так же из-за того, что субкнто имеют составной тип данных.

ИМХО, самый оптимальный алгоритм предложен Пашей GROOVY.
65 milan
 
17.08.11
08:32
Ждем результата замеров от ТС
Программист всегда исправляет последнюю ошибку.