Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 8 общая

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

посоветуйте  способы оптимизации запроса с таблицами значений
Я
   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 человек.
Рекламное место пустует