Имя: Пароль:
1C
1С v8
посоветуйте способы оптимизации запроса с таблицами значений
0 novichok79
 
23.10.17
16:03
Доброго времени суток, дорогие друзья!
Разрабатываю обработку. В ней 4 табличные части, часть кода выполняется на сервере. Все сделал, сама обработка притормаживает. Сделал замер времени - нашел 2 процедуры, которые выполняются чаще всего и сжирают больше всего времени:

[CODE]
&НаСервереБезКонтекста
Функция ПолучитьТаблицуУжеИспользованныхМатериалов(ТаблицаМатериалов, РасходМатериалов, НомерСтрокиПоПорядку)

    Запрос = Новый Запрос;
    МВТ = Новый МенеджерВременныхТаблиц;
    
    Запрос.МенеджерВременныхТаблиц = МВТ;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ТаблицаМатериалов.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал
    |ПОМЕСТИТЬ ВТТаблицаМатериалов
    |ИЗ
    |    &ТаблицаМатериалов КАК ТаблицаМатериалов
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    РасходМатериалов.НомерСтрокиПоПорядку КАК НомерСтрокиПоПорядку,
    |    РасходМатериалов.НоменклатураМатериал КАК НоменклатураМатериал,
    |    РасходМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    РасходМатериалов.КоличествоИспользуемое КАК КоличествоИспользуемое
    |ПОМЕСТИТЬ ВТРасходМатериалов
    |ИЗ
    |    &РасходМатериалов КАК РасходМатериалов
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ТаблицаМатериалов.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    СУММА(ЕСТЬNULL(РасходМатериалов.КоличествоИспользуемое, 0)) КАК КоличествоИспользуемое
    |ИЗ
    |    ВТТаблицаМатериалов КАК ТаблицаМатериалов
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТРасходМатериалов КАК РасходМатериалов
    |        ПО ТаблицаМатериалов.НоменклатураМатериал = РасходМатериалов.НоменклатураМатериал
    |            И ТаблицаМатериалов.ХарактеристикаМатериал = РасходМатериалов.ХарактеристикаМатериал
    |            И (РасходМатериалов.НомерСтрокиПоПорядку < &НомерСтрокиПоПорядку)
    |
    |СГРУППИРОВАТЬ ПО
    |    ТаблицаМатериалов.НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал
    |
    |УПОРЯДОЧИТЬ ПО
    |    НоменклатураМатериал,
    |    ХарактеристикаМатериал
    |АВТОУПОРЯДОЧИВАНИЕ";
    
    Запрос.УстановитьПараметр("ТаблицаМатериалов", ТаблицаМатериалов);
    Запрос.УстановитьПараметр("РасходМатериалов", РасходМатериалов.Выгрузить());
    Запрос.УстановитьПараметр("НомерСтрокиПоПорядку", НомерСтрокиПоПорядку);

    Результат = Запрос.Выполнить();
    МВТ.Закрыть();
    
    Возврат Результат.Выгрузить();

КонецФункции
[/CODE]

Каким образом можно оптимизировать данную процедуру? Переписать ее на вызовы НайтиСтроки, без выгружения таблицы формы РасходМатериалов?
Заранее благодарю ответивших.
1 novichok79
 
23.10.17
16:07
это первая процедура, вторая - тоже запрос с таблицами формы (которые выгружаются в таблицы значений в параметрах запроса)
2 novichok79
 
23.10.17
16:11
вторая процедура:

[CODE]
&НаСервереБезКонтекста
Функция ПолучитьТаблицуОстатковМатериаловНаСкладах(ТаблицаМатериалов, ОстаткиМатериаловНаСкладах)
    
    Запрос = Новый Запрос;
    МВТ = Новый МенеджерВременныхТаблиц;
    
    Запрос.МенеджерВременныхТаблиц = МВТ;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ВЫРАЗИТЬ(ТаблицаМатериалов.НоменклатураМатериал КАК Справочник.Номенклатура) КАК НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал
    |ПОМЕСТИТЬ ВТТаблицаМатериалов
    |ИЗ
    |    &ТаблицаМатериалов КАК ТаблицаМатериалов
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ОстаткиМатериаловНаСкладах.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    ОстаткиМатериаловНаСкладах.ПредставлениеМатериал КАК ПредставлениеМатериал,
    |    ОстаткиМатериаловНаСкладах.УпаковкаМатериал КАК УпаковкаМатериал,
    |    ОстаткиМатериаловНаСкладах.ОстатокМатериал КАК ОстатокМатериал
    |ПОМЕСТИТЬ ВТОстаткиМатериаловНаСкладах
    |ИЗ
    |    &ОстаткиМатериаловНаСкладах КАК ОстаткиМатериаловНаСкладах
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ОстаткиМатериаловНаСкладах.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.ПредставлениеМатериал, """") КАК ПредставлениеМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.УпаковкаМатериал, ТаблицаМатериалов.НоменклатураМатериал.ЕдиницаИзмерения) КАК УпаковкаМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.ОстатокМатериал, 0) КАК ОстатокМатериал
    |ИЗ
    |    ВТТаблицаМатериалов КАК ТаблицаМатериалов
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТОстаткиМатериаловНаСкладах КАК ОстаткиМатериаловНаСкладах
    |        ПО ТаблицаМатериалов.НоменклатураМатериал = ОстаткиМатериаловНаСкладах.НоменклатураМатериал
    |            И ТаблицаМатериалов.ХарактеристикаМатериал = ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал
    |
    |УПОРЯДОЧИТЬ ПО
    |    НоменклатураМатериал,
    |    ХарактеристикаМатериал
    |АВТОУПОРЯДОЧИВАНИЕ";
    
    Запрос.УстановитьПараметр("ТаблицаМатериалов", ТаблицаМатериалов);
    Запрос.УстановитьПараметр("ОстаткиМатериаловНаСкладах", ОстаткиМатериаловНаСкладах.Выгрузить());

    Результат = Запрос.Выполнить();
    МВТ.Закрыть();
    
    РезультатФункции = Результат.Выгрузить();

    Для Каждого СтрокаТаблицы Из РезультатФункции Цикл
        
        СтрокаТаблицы.ПредставлениеМатериал =
        ПредставлениеПозиции(СтрокаТаблицы.НоменклатураМатериал, СтрокаТаблицы.ХарактеристикаМатериал);

    КонецЦикла;

    Возврат РезультатФункции;

КонецФункции
[/CODE]
3 novichok79
 
23.10.17
16:12
вторая процедура берет 39% чистого времени, первая - 37%
4 Belomor
 
23.10.17
16:14
Попробуй проиндексировать временные таблицы
5 novichok79
 
23.10.17
16:15
(4) как вариант, спасибо.
6 Belomor
 
23.10.17
16:18
7 novichok79
 
23.10.17
16:19
(6) вот это ваще шикарный подгон.
8 novichok79
 
23.10.17
16:25
(6) из вышеперечисленного, только поля через точку (да и то не всего, когда есть Null) и соединения неиндексированных таблиц.
9 novichok79
 
24.10.17
10:02
в первой процедуре - индексировал таблицу по полю "НоменклатураМатериал"
во второй процедуре - перенес таблицу остатков в менеджер временных таблиц, который передаю в процедуру

первая процедура на 100 вызовов:

до - 5,439607 сек
после - 5,383516 сек

вторая процедура на 100 вызовов:

до - 5,302714 сек
после - 4,224232 сек

думаю сделать процедуры, которые бы вручную формировали нужные ТЗ без использования запросов, и проверить быстродействие на них.
10 Timon1405
 
24.10.17
10:27
можно попробовать
ИНДЕКСИРОВАТЬ ПО
НоменклатураМатериал,
ХарактеристикаМатериал
но без плана запроса все это пальцем в небо
11 novichok79
 
24.10.17
10:36
(10) база работает на PostgreSQL, не подскажете трассировщик?
12 novichok79
 
24.10.17
10:39
(11) понятно что там через explain делается, а как получить запрос к базе, который формирует сама 1С? через технологический журнал?
13 Timon1405
 
24.10.17
10:40
14 novichok79
 
24.10.17
10:46
(13) спасибо большое, сейчас изучу, мне походу нужен planSQLText
15 novichok79
 
24.10.17
11:55
первый раз парсю технологический журнал 1С, сильно не пинайте:

вторая процедура. тут делается менеджер временных таблиц

27:37.222043-1,DBPOSTGRS,6,process=rphost,p:processName=ut_11_test,t:clientID=42,t:applicationName=1CV8C,t:computerName=DOMASHNIYYOPTA,t:connectID=24,SessionID=2,Usr=Администратор,AppID=1CV8C,Trans=0,dbpid=7552,Sql='explain INSERT INTO pg_temp.tt33 (_Q_000_F_000RRef, _Q_000_F_001RRef, _Q_000_F_002, _Q_000_F_003RRef, _Q_000_F_004) SELECT
CAST(NULL AS BYTEA),
CAST(NULL AS BYTEA),
CAST(NULL AS MVARCHAR(1)),
CAST(NULL AS BYTEA),
CAST(NULL AS NUMERIC) LIMIT 0',Result=PGRES_TUPLES_OK,Context='Форма.Вызов : ВнешняяОбработка.Проба.Форма.ФормаОбработки.Модуль.ПриИзмененииНарядаНаРаботуНаСервере
ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1330 : ОбновитьТабличныеЧастиСвязанныеСНарядомНаРаботу();
    ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1362 : ЗаполнитьМинимальноеПроизведено(Объект.ПродукцияВНарядеНаРаботу, Объект.РасходМатериалов,
        ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2205 : МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах =
            ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2060 : Запрос.Выполнить();'
27:37.222044-3,DBPOSTGRS,5,process=rphost,p:processName=ut_11_test,t:clientID=42,t:applicationName=1CV8C,t:computerName=DOMASHNIYYOPTA,t:connectID=24,SessionID=2,Usr=Администратор,AppID=1CV8C,Trans=0,dbpid=7552,Sql='INSERT INTO pg_temp.tt33 (_Q_000_F_000RRef, _Q_000_F_001RRef, _Q_000_F_002, _Q_000_F_003RRef, _Q_000_F_004) SELECT
CAST(NULL AS BYTEA),
CAST(NULL AS BYTEA),
CAST(NULL AS MVARCHAR(1)),
CAST(NULL AS BYTEA),
CAST(NULL AS NUMERIC) LIMIT 0',RowsAffected=0,planSQLText='Insert on tt33  (cost=0.00..0.03 rows=1 width=146)
  ->  Subquery Scan on "*SELECT*"  (cost=0.00..0.03 rows=1 width=146)
        ->  Limit  (cost=0.00..0.01 rows=1 width=160)
              ->  Result  (cost=0.00..0.01 rows=1 width=160)
',RowsAffected=0,Context='Форма.Вызов : ВнешняяОбработка.Проба.Форма.ФормаОбработки.Модуль.ПриИзмененииНарядаНаРаботуНаСервере
ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1330 : ОбновитьТабличныеЧастиСвязанныеСНарядомНаРаботу();
    ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1362 : ЗаполнитьМинимальноеПроизведено(Объект.ПродукцияВНарядеНаРаботу, Объект.РасходМатериалов,
        ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2205 : МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах =
            ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2060 : Запрос.Выполнить();'

а тут вот получается сама таблица остатков

27:37.238000-15888,DBPOSTGRS,6,process=rphost,p:processName=ut_11_test,t:clientID=42,t:applicationName=1CV8C,t:computerName=DOMASHNIYYOPTA,t:connectID=24,SessionID=2,Usr=Администратор,AppID=1CV8C,Trans=0,dbpid=7552,Sql="explain analyse SELECT
T2._Q_000_F_000RRef,
T2._Q_000_F_001RRef,
COALESCE(CAST(T2._Q_000_F_002 AS MVARCHAR(300)),''::mvarchar),
COALESCE(T2._Q_000_F_003RRef,T3._Fld4172RRef),
COALESCE(CAST(T2._Q_000_F_004 AS NUMERIC(15, 3)),0),
T4._Folder,
T4._Description,
T4._IDRRef,
T5._Description,
T5._IDRRef
FROM pg_temp.tt26 T1
LEFT OUTER JOIN pg_temp.tt33 T2
ON ((T1._Q_001_F_000RRef = T2._Q_000_F_000RRef) AND (T1._Q_001_F_001RRef = T2._Q_000_F_001RRef))
LEFT OUTER JOIN _Reference166 T3
ON (T1._Q_001_F_000RRef = T3._IDRRef) AND (T3._Fld890 = 0)
LEFT OUTER JOIN _Reference166 T4
ON (T2._Q_000_F_000RRef = T4._IDRRef) AND (T4._Fld890 = 0)
LEFT OUTER JOIN _Reference309 T5
ON (T2._Q_000_F_001RRef = T5._IDRRef) AND (T5._Fld890 = 0)
ORDER BY (T4._Folder), (T4._Description), (T4._IDRRef), (T5._Description), (T5._IDRRef)",Result=PGRES_TUPLES_OK,Context='Форма.Вызов : ВнешняяОбработка.Проба.Форма.ФормаОбработки.Модуль.ПриИзмененииНарядаНаРаботуНаСервере
ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1330 : ОбновитьТабличныеЧастиСвязанныеСНарядомНаРаботу();
    ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 1362 : ЗаполнитьМинимальноеПроизведено(Объект.ПродукцияВНарядеНаРаботу, Объект.РасходМатериалов,
        ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2211 : ЗаполнитьМинимальноеПроизведеноВСтрокеПродукции(
            ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2245 : ТаблицаОстатковМатериалов =
                ВнешняяОбработка.Проба.Форма.ФормаОбработки.Форма : 2103 : РезультатПакет = Запрос.ВыполнитьПакет();'
16 novichok79
 
24.10.17
12:11
вторая функция, видно что каждый раз создается таблица из 214 записей на каждый вызов, и вызывается такая процедура 10 раз.
попробую все-таки переписать на ТЗ
17 novichok79
 
24.10.17
12:13
(16) не могу сюда вставку из журнала запостить - слишком много букв.
18 Timon1405
 
24.10.17
12:16
так индексировать условия соединения пробовали?
19 dezss
 
24.10.17
12:21
Нафейхоа тебе МВТ, если ты его потом не используешь?
Это уже лишние телодвижения и создание лишних сущностей.
20 novichok79
 
24.10.17
12:24
(19) там уже таблица висит, загружена один раз, вместо того, чтобы грузить ее постоянно в новый создаваемый МВТ.
(18) пробовал но прироста оно не дает, как мне кажется, нужно избежать загрузки таблицы в память, вместо этого надо иметь на момент вызова список накопленных значений в одной таблице, в которой просто искать накопленный остаток.
21 novichok79
 
24.10.17
12:26
(19) это кстати уже упомянуто в (9), там же есть сравнения по скорости выполнения.
22 piter3
 
24.10.17
12:27
номенклатура не составное субконто случаем
23 novichok79
 
24.10.17
12:28
(22) не, справочник ссылка номенклатура
24 piter3
 
24.10.17
12:34
ТаблицаМатериалов.НоменклатураМатериал.ЕдиницаИзмерения не гут
25 Широкий
 
24.10.17
12:37
(18) Какой нафиг индексировать? Там записей сотни тысяч что ли?
Скорее всего отжирается время на передачу таблицы на сервак.

Строку еще прибей:
Запрос.МенеджерВременныхТаблиц = МВТ;
26 novichok79
 
24.10.17
12:42
(25) процедура делается в цикле на серваке, вызов двух процедур идет с сервера на сервер, да еще и процедуры без контекста.
почему надо прибить строку?
27 dezss
 
24.10.17
12:51
(20) Где она висит, если ты сразу после выполнения грохаешь МВТ???
МВТ нужен только если ты именно этот набор данных будешь использовать дальше, в других случаях его вообще создавать не надо!
28 novichok79
 
24.10.17
12:54
(27) в первой процедуре, да, ты прав.
29 dezss
 
24.10.17
12:57
(28) а во второй как и где ты создаешь МВТ?
30 D_E_S_131
 
24.10.17
13:01
Зачем вообще все это делать через создание временных таблиц запросом, если в одном случае просто циферку расхода нужно определить, а во втором получить представление Номенклатура+Характеристика?
Уж лучше для первой процедуры создать отдельный регистр сведений, записать данные в него и считывать, а для второй новый документ с табличной частью под все поля этих ТЗ. (сарказм)
31 novichok79
 
24.10.17
13:33
(29) во второй в МВТ загружается таблица остатков, которая не меняется, и дальше в цикле делается запрос с присоединением таблицы с материалами, по которым нужно получить остаток и таблицы из менеджера временных таблиц, который передается в функцию.
32 dezss
 
24.10.17
14:15
(31) о боже...ты сказал "запрос в цикле"...
сейчас тебя заклеймят)))

К тому же, ты не показал код того, как это все делается. Может тебе можно это все сделать один запросом.
33 novichok79
 
24.10.17
14:26
(31) ну, как говорится - код в студию )))

&НаСервереБезКонтекста
Процедура ЗаполнитьМинимальноеПроизведено(ПродукцияВНарядеНаРаботу, РасходМатериалов,
    ВыбранныеМатериалы, ОстаткиМатериаловНаСкладах, ОстаткиМатериаловНаСкладахСУчетомРасхода)

    //pla 24.10.2017 --> оптимизирую аки боженька
    МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах =
    ПолучитьМенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах(ОстаткиМатериаловНаСкладах);
    //pla 24.10.2017 <--
    
    Для Каждого СтрокаПродукцияВНарядеНаРаботу Из ПродукцияВНарядеНаРаботу Цикл
        
        ЗаполнитьКоличествоИспользуемоеВСтрокеПродукции(СтрокаПродукцияВНарядеНаРаботу,
        РасходМатериалов, ОстаткиМатериаловНаСкладахСУчетомРасхода, МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах);

    КонецЦикла;

    //pla 24.10.2017 --> оптимизирую аки боженька
    МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах.Закрыть();
    //pla 24.10.2017 <--

КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаполнитьКоличествоИспользуемоеВСтрокеПродукции(СтрокаПродукцияВНарядеНаРаботу,
    РасходМатериалов, ОстаткиМатериаловНаСкладахСУчетомРасхода, МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах)
    
    ПараметрыОтбора = Новый Структура;
    НомерСтрокиНарядаНаРаботу = СтрокаПродукцияВНарядеНаРаботу.НомерСтрокиНарядаНаРаботу;

    ПараметрыОтбора.Очистить();
    ПараметрыОтбора.Вставить("НомерСтрокиНарядаНаРаботу", НомерСтрокиНарядаНаРаботу);
    
    УдаляемыеСтроки = ОстаткиМатериаловНаСкладахСУчетомРасхода.НайтиСтроки(ПараметрыОтбора);
    
    Для Каждого УдаляемаяСтрока Из УдаляемыеСтроки Цикл
        
        ОстаткиМатериаловНаСкладахСУчетомРасхода.Удалить(УдаляемаяСтрока);
        
    КонецЦикла;
    
    РасходМатериаловДляТекущейПродукции = РасходМатериалов.НайтиСтроки(ПараметрыОтбора);
    
    ТаблицаМатериалов = РасходМатериалов.Выгрузить(РасходМатериаловДляТекущейПродукции);
    ТаблицаМатериалов.Свернуть("НоменклатураМатериал, ХарактеристикаМатериал");
    ТаблицаМатериалов.Индексы.Добавить("НоменклатураМатериал");

    ТаблицаОстатковМатериалов = ПолучитьТаблицуОстатковМатериаловНаСкладах(ТаблицаМатериалов, МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах);
    
    ТаблицаУжеИспользованныхМатериалов =
    ПолучитьТаблицуУжеИспользованныхМатериалов(ТаблицаМатериалов, РасходМатериалов, НомерСтрокиНарядаНаРаботу);
    
    НедостачаВсего = 0;
    ИзбытокВсего = 0;
    
    Для Каждого СтрокаРасходМатериаловДляТекущейПродукции Из РасходМатериаловДляТекущейПродукции Цикл
        
        ПараметрыОтбора.Очистить();
        
        ПараметрыОтбора.Вставить("НоменклатураМатериал", СтрокаРасходМатериаловДляТекущейПродукции.НоменклатураМатериал);
        ПараметрыОтбора.Вставить("ХарактеристикаМатериал", СтрокаРасходМатериаловДляТекущейПродукции.ХарактеристикаМатериал);
        
        НайденныеСтроки = ТаблицаОстатковМатериалов.НайтиСтроки(ПараметрыОтбора);
        
        Если НайденныеСтроки.Количество() > 0 Тогда
            
            НайденнаяСтрока = НайденныеСтроки.Получить(0);
            ОстатокМатериал = НайденнаяСтрока.ОстатокМатериал;
            
        Иначе ОстатокМатериал = 0;
        КонецЕсли;
        
        НайденныеСтроки = ТаблицаУжеИспользованныхМатериалов.НайтиСтроки(ПараметрыОтбора);
        
        Если НайденныеСтроки.Количество() > 0 Тогда
            
            НайденнаяСтрока = НайденныеСтроки.Получить(0);
            КоличествоИспользуемое = НайденнаяСтрока.КоличествоИспользуемое;
            
        Иначе КоличествоИспользуемое = 0;
        КонецЕсли;
        
        ОстатокМатериалСУчетомРасхода =
        Макс(0, ОстатокМатериал - КоличествоИспользуемое);
        
        СтрокаОстаткиМатериаловНаСкладахСУчетомРасхода = ОстаткиМатериаловНаСкладахСУчетомРасхода.Добавить();
        ЗаполнитьЗначенияСвойств(СтрокаОстаткиМатериаловНаСкладахСУчетомРасхода, СтрокаРасходМатериаловДляТекущейПродукции);
        
        СтрокаОстаткиМатериаловНаСкладахСУчетомРасхода.ОстатокМатериал = ОстатокМатериал;
        СтрокаОстаткиМатериаловНаСкладахСУчетомРасхода.КоличествоИспользуемое = КоличествоИспользуемое;
        СтрокаОстаткиМатериаловНаСкладахСУчетомРасхода.ОстатокМатериалСУчетомРасхода = ОстатокМатериалСУчетомРасхода;
        
        СтрокаРасходМатериаловДляТекущейПродукции.КоличествоИспользуемое =
        Мин(СтрокаРасходМатериаловДляТекущейПродукции.КоличествоТребуемое, ОстатокМатериалСУчетомРасхода);
        
        Если СтрокаРасходМатериаловДляТекущейПродукции.КоличествоИспользуемое < 0 Тогда
            
            СтрокаРасходМатериаловДляТекущейПродукции.КоличествоИспользуемое = 0;
            
        КонецЕсли;
        
        КоличествоОстаток = СтрокаРасходМатериаловДляТекущейПродукции.КоличествоТребуемое -
        СтрокаРасходМатериаловДляТекущейПродукции.КоличествоИспользуемое;
        
        Если КоличествоОстаток > 0 Тогда
            
            СтрокаРасходМатериаловДляТекущейПродукции.Недостача = КоличествоОстаток;
            СтрокаРасходМатериаловДляТекущейПродукции.Избыток = 0;
            
        ИначеЕсли КоличествоОстаток < 0 Тогда
            
            СтрокаРасходМатериаловДляТекущейПродукции.Недостача = 0;
            СтрокаРасходМатериаловДляТекущейПродукции.Избыток = -КоличествоОстаток;
            
        Иначе
            
            СтрокаРасходМатериаловДляТекущейПродукции.Недостача = 0;
            СтрокаРасходМатериаловДляТекущейПродукции.Избыток = 0;
            
        КонецЕсли;
        
        НедостачаВсего = НедостачаВсего + СтрокаРасходМатериаловДляТекущейПродукции.Недостача;
        ИзбытокВсего = ИзбытокВсего + СтрокаРасходМатериаловДляТекущейПродукции.Избыток;
        
    КонецЦикла;
    
    СтрокаПродукцияВНарядеНаРаботу.Недостача = НедостачаВсего;
    СтрокаПродукцияВНарядеНаРаботу.Избыток = ИзбытокВсего;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьТаблицуОстатковМатериаловНаСкладах(ТаблицаМатериалов, МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах)
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблицСОстаткамиМатериаловНаСкладах;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ВЫРАЗИТЬ(ТаблицаМатериалов.НоменклатураМатериал КАК Справочник.Номенклатура) КАК НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал
    |ПОМЕСТИТЬ ВТТаблицаМатериалов
    |ИЗ
    |    &ТаблицаМатериалов КАК ТаблицаМатериалов
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ОстаткиМатериаловНаСкладах.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.ПредставлениеМатериал, """") КАК ПредставлениеМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.УпаковкаМатериал, ТаблицаМатериалов.НоменклатураМатериал.ЕдиницаИзмерения) КАК УпаковкаМатериал,
    |    ЕСТЬNULL(ОстаткиМатериаловНаСкладах.ОстатокМатериал, 0) КАК ОстатокМатериал
    |ИЗ
    |    ВТТаблицаМатериалов КАК ТаблицаМатериалов
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТОстаткиМатериаловНаСкладах КАК ОстаткиМатериаловНаСкладах
    |        ПО ТаблицаМатериалов.НоменклатураМатериал = ОстаткиМатериаловНаСкладах.НоменклатураМатериал
    |            И ТаблицаМатериалов.ХарактеристикаМатериал = ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал
    |
    |УПОРЯДОЧИТЬ ПО
    |    НоменклатураМатериал,
    |    ХарактеристикаМатериал
    |АВТОУПОРЯДОЧИВАНИЕ
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |УНИЧТОЖИТЬ ВТТаблицаМатериалов";
    
    Запрос.УстановитьПараметр("ТаблицаМатериалов", ТаблицаМатериалов);
    РезультатПакет = Запрос.ВыполнитьПакет();

    Результат = РезультатПакет.Получить(РезультатПакет.ВГраница() - 1);
    РезультатФункции = Результат.Выгрузить();

    Для Каждого СтрокаТаблицы Из РезультатФункции Цикл
        
        СтрокаТаблицы.ПредставлениеМатериал =
        ПредставлениеПозиции(СтрокаТаблицы.НоменклатураМатериал, СтрокаТаблицы.ХарактеристикаМатериал);

    КонецЦикла;

    Возврат РезультатФункции;

КонецФункции
34 dezss
 
24.10.17
14:41
(33) мда...вот тут и есть запрос в цикле...
А не пробовал все это сделать один мегазапросом?
35 novichok79
 
24.10.17
14:55
(34) так расчет идет в цикле, если бы таблицы не менялись, то как нефиг делать.
пока так поработают, потом перепишу на как можно меньшее количество серверных вызовов.
всем спасибо за помощь.
36 novichok79
 
27.10.17
12:34
переписал процедуры интерактивных действий на клиенте (при изменении количества, варианта комплектации), таким образом, чтобы они выполнялись только на клиенте.
в итоге вместо 5133 мс, процедура выполняется 108 мс.
Пользователь не знает, чего он хочет, пока не увидит то, что он получил. Эдвард Йодан