Имя: Пароль:
1C
1C 7.7
v7: Оптимизировать процедуру 1c7.7_SQL
0 _traktor_
 
02.10.23
22:37
Обьем базы 9 гб
Сервер: SQL2008+Server2016(ram64Gb+RAID10)+LAN_1GB
Клиенты: i5+ram8Gb

Достаточно долгое формирование обработки, более 10 минут.
https://cloud.mail.ru/public/3u7V/9z6yuyqKg
Какие варианты оптимизации кода ?
1 Злопчинский
 
02.10.23
22:48
тебе забесплатно отрефакторить/переписать?
.
вариант оптимизации самый первый если владеешь - прямые запросы.
.
10 минут ни о чем не говорит. что в итоге этих 10 минут получается? простыня на 100 тыс строк?
2 Злопчинский
 
02.10.23
22:49
штатно тоже можно ускорить, но надо СМОТРЕТЬ ПРЕДМЕТНО если нужен хороший результат.
3 Злопчинский
 
02.10.23
22:50
О... это еще на бухкомпоненте...
4 Харлампий Дымба
 
02.10.23
22:51
Круть. А кто-нибудь помнит что означали {} в условии запроса ? Это 7.0 или 7.5 было.
Сейчас попробую чуть-чуть посмотреть, без советов переписать всё на прямые запросы.
5 Злопчинский
 
02.10.23
22:54
занятная конструкция, никогда не использовал...
Условие ({СокрЛП(ВыбАртикул)} в СокрЛП(Артикул))
.
почему не тупо на равенство строк?
6 Злопчинский
 
02.10.23
22:56
(4) я вообще хз что такое с фигурными скобками в части синтаксиса запросов, никогда не юзал
7 Злопчинский
 
02.10.23
23:00
(0) Попробовать: все переменные запроса если они не используются в группировках/условиях - убрать. В коде их дергать через точку там где они нужны.
8 Злопчинский
 
02.10.23
23:02
Группировка Товар Без групп;
в коде убрать проверки Запрос.Товар.ЭтоГруппа()=1
9 Злопчинский
 
02.10.23
23:04
Многоэтажную хрень если и циклов с анализом флажков группировок переделать нахрен по образу и подобию как в ТиС список значений группировок (Отчет ОстаткиТМЦ), разбираться в этой лапше совсем не хочется
10 Злопчинский
 
02.10.23
23:07
Убрать нахрен консруктцию Таб.ПрисоединитьСекцию - это тормозная штука при выводе очета. Проще сделать два макета - с короткой строкой и с длинной строкой и задавать исходный макет в зависимости от флажков.
11 Злопчинский
 
02.10.23
23:08
Убрать работу с областями, это тоже тормозная штука.
оформит сразу как надо - даже если попроще пусть убдет
                                                Обл = Таб.Область(НачСтрока,7);    
Обл.РамкаСправа(3);
12 Злопчинский
 
02.10.23
23:10
ну и хорошо бы привести пример замера, на чем жрется время
13 Злопчинский
 
02.10.23
23:13
хз что там у вас в
ПолучитьЦенуТМЦ()
если периодика там дергается - то и тут тормоза будут, особенно если таких операций много или переписывать или переходить на объект "Периодический" - дает прирост при работе в периодическими реквизитами ~25%
14 Злопчинский
 
02.10.23
23:15
чисто приколоться.. надо было еще сложнее написать..
.
//*******************************************
Процедура ПриВыбреМестаХранения()
    Если МестоХранения.Выбран() = 0 Тогда
        Форма.ПоСкладам.Видимость(1);
    Иначе
        Форма.ПоСкладам.Видимость(0);
    КонецЕсли;
КонецПроцедуры
.
Форма.ПоСкладам.Видимость(1-МестоХранения.Выбран());
15 Злопчинский
 
02.10.23
23:20
в ВыбТовары = Только товары, группы не класть и попробовать вместо
"Условие (Товар в {ВыбТовары});"
.
условие убрать
фильтровать при обходе группировки по товарам по типу
Если ВыбТовары.НайтиЗначение(Запрос.Товар)=0 Тогда Продолжить; КонецЕсли;
.
может получиться охеренный итоговый прирост скорости выполнения
16 Злопчинский
 
03.10.23
10:28
на сем мое волонтерсов закончилось. думать влом.
Харлампий Дымба накинет еще, может и отчет перепишет.. он такой..
17 Харлампий Дымба
 
02.10.23
23:35
Всё ниже - моё мнение, пусть меня поправят, если  не прав.
Все вот такие условия в запросе:
"Условие (ПустаяСтрока(ТоварнаяГруппа)=0);"
плохи вызовом функций 1С, лучше задать
ПустаяТоварнаяГруппа=ПолучитьПустоеЗначение("Справочник.ТоварныеГруппы")
и в условии писать
Условие (ТоварнаяГруппа<>ПустаяТоварнаяГруппа);

Все вот такие условия
Условие(Товар.ВидНоменклатуры = ВидНоменклатуры)
хуже чем
ВидНоменклатурыТовара    = Регистр.ОстаткиТоваров.Номенклатура.ВидНоменклатуры;
Условие(ВидНоменклатурыТовара = ВидНоменклатуры)

Если в группировках - элементы справочник, а группы не нужны - пиши "Группировка Склад без групп"
если не важен порядок и не планируешь испоьзовать потом наименование элементов из группировки - пиши "Группировка Склад без групп без Упорядочивания", если планируешь использовать наименование Упорядочить по Склад.Наименование

Запрос.Товар.ЭтоГруппа() плохо тем, что ты впустую считываешь объект из базы (он тебе дальше не нужен) -
пиши Запрос.ЭтоГруппа("Товар")

ПолучитьЦенуТМЦ(Запрос.Товар,ДатаОтчета) - не вижу что в коде, но очень подозреваю, что там что-то типа
Товар.Цена.Получить(ДатаОтчета)
лучше переписать
гл_П1.ИспользоватьОбъект("Цена",Товар);
Возврат гл_П1.ЗначениеНаДату(НаДату);
где глП_1 - глобальная переменная, которая инициализируется в глобальном модуле (не в функции ПолучитьЦенуТМЦ!), т.е. в конце глобального модуля
П=СоздатьОбъект("Периодический");

В макете отчета не пиши
Запрос.Товар.Наименование
во-первых используй уже подготовленную переменную, а в ячейку пиши уже ее
ПечТовар=Запрос.Товар.Наименование
в группировке в запросе напиши Упорядочить По Товар.Наименование
а ячейке присваивай
ПечТовар=Запрос.ЗначениеУпорядочивания(1)
либо в запросе сразу делай переменную
АртикулТовара=Запрос.Товар.Артикул
и пиши
ПечАртикул=Запрос.АртикулТовара

Запрос.Товар.Цвет.Наименование - ооооочень долго

перепиши все так, чтобы по возможности не было
Реквизит=Запрос.ЭлементСправочника.РеквизитСправочника
если нельзя обойтись без этого, тогда хотя бы так:
Элемент=Запрос.ЭлементСправочника;
Реквизит=Элемент.РеквизитСправочника;

форматирование в ячейках таблиц типа #N12.2. - можно оставить как есть, там выиграша не будет.

можно в принципе и текст запроса составлять так, чтобы не получать лишних реквизитов - если не поставили группировку или отбора по складу - то
Склад    = Регистр.ОстаткиТоваров.МестаХранения;
можно убирать

по бухитогам вопросов нет

Воспользуйся замером производительности в отладчике - включи часы в начала отчета, выключи после окончания, посмотри время

Это основное, что ты можешь выжать из обычных 1совских отчетов
18 Харлампий Дымба
 
02.10.23
23:37
(16) Хехе - чуть не один в один)
19 Злопчинский
 
02.10.23
23:41
(18) а что делать... Если в руках молоток - весь мир состоит из гвоздей...
20 Djelf
 
03.10.23
11:46
(6) На ИТС есть описание фигурных скобок: https://its.1c.ru/db/metod8dev/content/2511/hdoc
(0) Попробуй Запрос.ВключитьSQL(0);
Смутно помнится, что на тупящих запросах на sql базах это помогало.
21 Харлампий Дымба
 
03.10.23
10:54
(20) Это про скобки в 8. В 7.7 же, насколько помнится, скобки  остались как анахронизм от версии 7.0 - ими предполагалось выделять переменные модуля, используемые в запросе, в отличие от переменных запроса. А в 7.0 они попали так как широко использовались в 6.0 для указания макроимени (ссылки) субконто типовой операции..
К 7.7 решили, что скобки - лишнее, но синтаксис оставили для совместимости. Попробовал сейчас, думал что можно будет с помощью этих скобок иметь возможность использовать одинаковые имена для переменных запрос и модуля, типа "Условие (Товар в {Товар})", но нет, не работает. Так что скобки не нужны от слова "совсем".

(20) Запрос.ВключитьSQL(0) - как правило, наоборот резко замедляет скорость формирования запроса. Этот переключатель, чтобы сформировать запрос, не как sql-ный, а как dbf-ный. Использовался, видимо самой 1С, для отладки, чтобы понять не косячит ли sql-ный запрос и даёт ли те же данные, что и dbf-ный.
В некоторых случаях как раз и помогает обойти оставшиеся косяки sql-ных запросов, например
Условие (ДатаДок в СписокДат) в sql у меня не работает, а в DBF - без проблем. Поэтому надо или
Запрос.ВключитьSQL(0);
или
Условие (СписокДат.НайтиЗначение(ДатаДок)>0)
И второе всё равно работает гораздо быстрее.

(0) Ах да, ещё у тебя там "Группировка Партия" - убери для тех типов цен, где она не нужна. Тут хорошая прибавка будет.
Ну и в ТЗ в цикле группировки по партиям зачем пихать каждый раз .НоваяСтрока с тем же товаром? Чтоб потом делать ТЗ.Свернуть с миллионом строк? Лучше посчитай в цикле итоговую сумму по товару, и потом добавь в ТЗ одной строкой.
А вообще - "Замер производительности" и смотри на чем проигрываешь, может у тебя Запрос.Выполнить - 10% от времени, а остальное это неоптимальный алгоритм обработки полученных данных.
22 Djelf
 
03.10.23
11:36
(21) Ну да, для 8ки, но что-то схожее видимо есть..
В том то и дело что "как правило", попробовать все равно стоит.
23 Злопчинский
 
03.10.23
13:11
(21) Условие (ДатаДок в СписокДат) в sql у меня не работает
- проверь когда в списке одно значение и когда несколько
24 vladmenleo
 
03.10.23
13:27
(0) Переписать все на прямой запрос из 1с++. Лучше полчаса потерять, зато потом за 5 минут долететь (с)
25 Chai Nic
 
03.10.23
13:31
(24) +1
Черные запрос на sql часто работает неадекватно - вытягивает половину базы в temp в виде dbf-файлов и дальше обрабатывает уже их. Сталкивался с подобным отчетом по продажам, который формировался чуть ли не полчаса. Простой перебор документов был на несколько порядков быстрее.
26 Злопчинский
 
03.10.23
13:32
(25) это зависит от того как написаны условия. если "неправильно" - тогда тянется результат "запроса" в темп и на него дополнительно накатывают условия и потом выдают как результат "запроса"
27 Злопчинский
 
03.10.23
13:36
(26) .. хотя это я на дбф наблюдал, а вот как на скуле - хз...
28 vladmenleo
 
03.10.23
13:37
(26) Именно так, все от условий. Частенько оптимально засунуть результат во временную таблицу на сервере, а потом из нее выбрать по условию
29 vladmenleo
 
03.10.23
13:43
(26) Ступил, речь про черный запрос. Почти пять лет в конторе, все на прямых запросах
30 Chai Nic
 
03.10.23
13:52
(27) А на sql так же, только хуже))
31 Злопчинский
 
03.10.23
14:04
я столнулся с тем что на скуле
Условие(Номенклатура в Сзноменклатура);
- адски тормозило.
проще было собрать запрос без фильтра по товарам (даже если товаров было очень много)
и уже при обходе результат запроса фильтровать вручную через СЗНоменклатура.НайтиЗначение(Запрос.Номенклатура).
.
почему так - хз, может как-то криво секретный релиз поставлен или еще что...
32 АгентБезопасной Нацио
 
03.10.23
14:43
(25) ага, а все потому, что sql в клюшках используется как тупое таблицохранилище. поэтому оно, грубо говоря, тянет весь селект-лист на клиента в дбф (фильтруя только, емнип, по общим реквизитам доков), а уже там строит индексы для других отборов.
(24) категорически согласен.
33 Злопчинский
 
03.10.23
15:28
(24) (32) Ну дык и помогите страждущему ;-)
34 Arbuz
 
03.10.23
15:37
(24) В оригинале было:
Лучше день потерять, зато потом за 5 минут долететь (с)

Я не знаю как там на mssql обстоят дела, но прямые на dbf через 1sqlite у меня дают типичный выигрыш более двух порядков (я где-то отмечал, что в ТиС на запросе в СписаниеТМЦ я получил выигрыш в 8000 раз). Уже только это заставило меня не думать о чорных запросах совсем никогда. Не считая того, что в прямой запрос можно переложить значительную часть логики постобработки, что ещё ускоряет итог.

Бедные снеговиководы, через плечо заглядывая с неприкрытой жалостью и брезглиговостью на уродские клюшки, так и не могут поверить своим глазам, когда видят, что у меня средняя скорость проведения документа в потоке при очень активных юзерах < 70мс на оборудовании чья производительность уступает паре смарт-чайников. Есть, конечно, БП'шный снеговик куда всё консолидируется из клюшек - удобный, красивый, современный, упитанный, уверенный и лоснящийся.
35 Злопчинский
 
03.10.23
15:41
(34) я прямые не осилил, только самое простое. Просто надобности не было, не работал я в нагруженных системах с большим количеством пользователей, пичалька...
36 АгентБезопасной Нацио
 
03.10.23
16:16
(33)
"-Господи, ну помоги же Абраму выйграть в лотерею!
--Да я бы помог, но пусть он хоть раз купит лотерейный билет!"
©
Я в том смысле, что пусть хотя бы трассировку сделает, определит, где основные тормоза... а то накинул, и пропал..

Да и клюшек под рукой нет, проверить. Запрос-то и руками написать не проблема, но малейший косяк в синтаксисе - и будет бодяга на пару недель, судя по скорости реакции ТСа
37 vladmenleo
 
03.10.23
16:39
(33) (0) В первом приближении как-то так
ТзЗапрос = СоздатьОбъект("ТаблицаЗначений");
    ЗапросДляТЗ = СоздатьОбъект("ODBCRecordSet");
    ТекстЗапроса = "
    |Select
    |    Рег.МестаХранения as [Склад $Справочник.Склады],
    |    Тов.ID as [Товар $Справочник.Номенклатура],
    |    $Тов.Артикул as Артикул,
    |    $Тов.Рисунок as Рисунок,
    |    $Тов.ТоварнаяГруппа as [ТоварнаяГруппа $Справочник.ТоварныеГруппы], -- ????? Если это справочник
    |    Рег.Партии as Партия,
    |    Рег.КоличествоОстаток as КонКол,
    |    $Тов.КоэффПересчета as КоэфТук,
    |From                                                                                                                                  
    |    $РегистрОстатки.ОстаткиТоваров(:ДатаОтчета~,, " + ?(МестоХранения.Выбран()=0, "", "Рег.МестаХранения = :МестоХранения") + ") as Рег
    |Inner Join
    |    $Справочник.Номенклатура Тов WITH (NOLOCK) ON Тов.ID = Рег.Номенклатура
    |where 1 = 1
    |" + ?(ВыбТовары.РазмерСписка() > 0, "and Тов.ID in (Select Val From #СписокТоваров)", "")+ "
    |";
    ЗапросДляТЗ.УстановитьТекстовыйПараметр("ДатаОтчета", ДатаОтчета);
    ЗапросДляТЗ.УстановитьТекстовыйПараметр("МестоХранения", МестоХранения);
    ЗапросДляТЗ.УложитьСписокОбъектов(ВыбТовары,"#СписокТоваров", "Номенклатура");
    ТзЗапрос = ЗапросДляТЗ.ВыполнитьИнструкцию(ТекстЗапроса);
Дальше по аналогии добавить условий
38 vladmenleo
 
03.10.23
16:47
(34) Про оригинал согласен, но на прямой запрос переписать полчаса, ну час от силы. Зато потом на черные запросы смотреть не захочется
Независимо от того, куда вы едете — это в гору и против ветра!