Вход | Регистрация


1С:Предприятие ::

Метки: 

посоветуйте способы оптимизации запроса с таблицами значений

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

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

    Запрос = Новый Запрос;
    МВТ = Новый МенеджерВременныхТаблиц;
    
    Запрос.МенеджерВременныхТаблиц = МВТ;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТаблицаМатериалов.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ТаблицаМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал
    |ПОМЕСТИТЬ ВТТаблицаМатериалов
    |ИЗ
    |    &ТаблицаМатериалов КАК ТаблицаМатериалов
    |;
    |
    ////////////////////////////////////////////////////////////////////////////////

    |ВЫБРАТЬ
    |    РасходМатериалов.НомерСтрокиПоПорядку КАК НомерСтрокиПоПорядку,
    |    РасходМатериалов.НоменклатураМатериал КАК НоменклатураМатериал,
    |    РасходМатериалов.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    РасходМатериалов.КоличествоИспользуемое КАК КоличествоИспользуемое
    |ПОМЕСТИТЬ ВТРасходМатериалов
    |ИЗ
    |    &РасходМатериалов КАК РасходМатериалов
    |;
    |
    ////////////////////////////////////////////////////////////////////////////////

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

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

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

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

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

    |ВЫБРАТЬ
    |    ОстаткиМатериаловНаСкладах.НоменклатураМатериал КАК НоменклатураМатериал,
    |    ОстаткиМатериаловНаСкладах.ХарактеристикаМатериал КАК ХарактеристикаМатериал,
    |    ОстаткиМатериаловНаСкладах.ПредставлениеМатериал КАК ПредставлениеМатериал,
    |    ОстаткиМатериаловНаСкладах.УпаковкаМатериал КАК УпаковкаМатериал,
    |    ОстаткиМатериаловНаСкладах.ОстатокМатериал КАК ОстатокМатериал
    |ПОМЕСТИТЬ ВТОстаткиМатериаловНаСкладах
    |ИЗ
    |    &ОстаткиМатериаловНаСкладах КАК ОстаткиМатериаловНаСкладах
    |;
    |
    ////////////////////////////////////////////////////////////////////////////////

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

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

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

    КонецЦикла;

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

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

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

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

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

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

думаю сделать процедуры, которые бы вручную формировали нужные ТЗ без использования запросов, и проверить быстродействие на них.
   Timon1405
 
10 - 24.10.17 - 10:27
можно попробовать
ИНДЕКСИРОВАТЬ ПО
НоменклатураМатериал,
ХарактеристикаМатериал
но без плана запроса все это пальцем в небо
 
 Рекламное место пустует
   novichok79
 
11 - 24.10.17 - 10:36
(10) база работает на PostgreSQL, не подскажете трассировщик?
   novichok79
 
12 - 24.10.17 - 10:39
(11) понятно что там через explain делается, а как получить запрос к базе, который формирует сама 1С? через технологический журнал?
   Timon1405
 
13 - 24.10.17 - 10:40
   novichok79
 
14 - 24.10.17 - 10:46
(13) спасибо большое, сейчас изучу, мне походу нужен planSQLText
   novichok79
 
15 - 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 : РезультатПакет = Запрос.ВыполнитьПакет();'
   novichok79
 
16 - 24.10.17 - 12:11
вторая функция, видно что каждый раз создается таблица из 214 записей на каждый вызов, и вызывается такая процедура 10 раз.
попробую все-таки переписать на ТЗ
   novichok79
 
17 - 24.10.17 - 12:13
(16) не могу сюда вставку из журнала запостить - слишком много букв.
   Timon1405
 
18 - 24.10.17 - 12:16
так индексировать условия соединения пробовали?
   dezss
 
19 - 24.10.17 - 12:21
Нафейхоа тебе МВТ, если ты его потом не используешь?
Это уже лишние телодвижения и создание лишних сущностей.
   novichok79
 
20 - 24.10.17 - 12:24
(19) там уже таблица висит, загружена один раз, вместо того, чтобы грузить ее постоянно в новый создаваемый МВТ.
(18) пробовал но прироста оно не дает, как мне кажется, нужно избежать загрузки таблицы в память, вместо этого надо иметь на момент вызова список накопленных значений в одной таблице, в которой просто искать накопленный остаток.
   novichok79
 
21 - 24.10.17 - 12:26
(19) это кстати уже упомянуто в (9), там же есть сравнения по скорости выполнения.
   piter3
 
22 - 24.10.17 - 12:27
номенклатура не составное субконто случаем
   novichok79
 
23 - 24.10.17 - 12:28
(22) не, справочник ссылка номенклатура
   piter3
 
24 - 24.10.17 - 12:34
ТаблицаМатериалов.НоменклатураМатериал.ЕдиницаИзмерения не гут
   Широкий
 
25 - 24.10.17 - 12:37
(18) Какой нафиг индексировать? Там записей сотни тысяч что ли?
Скорее всего отжирается время на передачу таблицы на сервак.

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

К тому же, ты не показал код того, как это все делается. Может тебе можно это все сделать один запросом.
   novichok79
 
33 - 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);
    РезультатФункции = Результат.Выгрузить();

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

    КонецЦикла;

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

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



Список тем форума
Рекламное место пустует Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует