Имя: Пароль:
1C
1С v8
Оптимизация запроса
0 makss89
 
16.04.14
14:27
Помогите оптимизировать фрагмент кода

Процедура ОбработкаПроведения(Отказ, Режим)

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

    Пока Выборка.Следующий() Цикл
        Предупреждение("Недостаточно остатков на складе!");        
        Отказ = Истина;
    КонецЦикла;
    
    Если Не Отказ Тогда
        ТекущееКоличество = Константы.КоличествоПроведенныхДокументов.Получить();            Константы.КоличествоПроведенныхДокументов.Установить(ТекущееКоличество + 1);
    КонецЕсли;

    …

КонецПроцедуры // ОбработкаПроведения()
1 Wobland
 
16.04.14
14:28
никаких предупреждений. с вас 300 рублей
2 Maxus43
 
16.04.14
14:29
1. вложенный запрос в ВТ
2. Убрать ВТ
3. Переделать запрос
3 Wobland
 
16.04.14
14:29
>Константы.КоличествоПроведенныхДокументов
аж прослезился
4 Maxus43
 
16.04.14
14:30
Лучше просто посмотри в типовых, контроль остатков - в каждом документе почти
5 vicof
 
16.04.14
14:31
(3) Спасибо, поржал))))
6 PR
 
16.04.14
14:34
(3) Слёзы умиления навернулись на глаза :))
7 GANR
 
16.04.14
14:35
(0) Если платформа не ниже 8.2 - вполне можно сначала записать движения со свойством БлокироватьДляИзменения = Истина, затем сделать запрос к остаткам по регистру в разрезе всех измерений и с условием Количество < 0, если запрос что-то вернул - ставим Отказ = Истина и возврат. Понятно?
8 makss89
 
16.04.14
14:41
Дело в том что я не программист, не могли бы вы написать как будет выглядеть оптимизированный код
9 vicof
 
16.04.14
14:42
(8) Может быть, поручить оптимизацию программисту?
10 Wobland
 
16.04.14
14:42
(8) отдай это дело программисту
11 makss89
 
16.04.14
14:44
Нужно срочно, помогите плиз если не сложно
12 Maxus43
 
16.04.14
14:45
хватит тролить то господа, сделайте доброе дело
13 Wobland
 
16.04.14
14:46
(11) речь об оптимизации. значит, работает. значит, не срочно
14 makss89
 
16.04.14
14:50
ну там же наверняка не долго это сделать...может поможете, я просто ничего в этом не понимаю
15 vicof
 
16.04.14
14:51
(14) Что тебе конкретно нужно оптимизировать? скорость, количество строк кода? сжираемую память?
16 Wobland
 
16.04.14
14:52
(14) мне лениво. держи мою старую поделку

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    //контроль остатков
    Отбор=Новый Структура("Разрез", Перечисления.РазрезыУчётнойПолитики.КонтрольОстатков);
    Если РегистрыСведений.УчётнаяПолитика.СрезПоследних(Дата, Отбор)[0].Значение Тогда
        Запрос=Новый Запрос;
        Запрос.Текст=
        "ВЫБРАТЬ
        |    ПартииТоваровОстатки.Номенклатура,
        |    СУММА(РасходнаяНакладнаяТовары.Количество) КАК КоличествоВДокументе,
        |    СУММА(ЕСТЬNULL(ПартииТоваровОстатки.КоличествоОстаток, 0)) КАК КоличествоОстаток
        |ИЗ
        |    Документ.РасходнаяНакладная.Товары КАК РасходнаяНакладнаяТовары
        |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваров.Остатки(&Период, Номенклатура В (&Номенклатура)) КАК ПартииТоваровОстатки
        |        ПО РасходнаяНакладнаяТовары.Номенклатура = ПартииТоваровОстатки.Номенклатура
        |ГДЕ
        |    РасходнаяНакладнаяТовары.Ссылка = &Ссылка
        |
        |СГРУППИРОВАТЬ ПО
        |    ПартииТоваровОстатки.Номенклатура
        |
        |ИМЕЮЩИЕ
        |    СУММА(РасходнаяНакладнаяТовары.Количество) >= СУММА(ЕСТЬNULL(ПартииТоваровОстатки.КоличествоОстаток, 0))";
        Запрос.УстановитьПараметр("Период", Дата);
        Запрос.УстановитьПараметр("Номенклатура", Товары.ВыгрузитьКолонку("Номенклатура"));
        Запрос.УстановитьПараметр("Ссылка", Ссылка);
        Выборка=Запрос.Выполнить().Выбрать();
        Пока Выборка.Следующий() Цикл
            Отказ=Истина;
            Сообщить("Недостаточно товара "+Выборка.Номенклатура+"; имеется: "+Выборка.КоличествоОстаток+"; требуется: "+Выборка.КоличествоВДокументе);
        КонецЦикла;
        Если Выборка.Количество() Тогда
            Возврат;
        КонецЕсли;
    КонецЕсли;
    
    // Продажи
    Для Каждого ТекСтрока Из Товары Цикл
        Движение=Движения.Продажи.Добавить();
        Движение.Период=Дата;
        Движение.Контрагент=Контрагент;
        Движение.Номенклатура=ТекСтрока.Номенклатура;
        Движение.Количество=ТекСтрока.Количество;
        Движение.Стоимость=ТекСтрока.Стоимость;
    КонецЦикла;
    Движения.Продажи.Записать();
    
    //ПартииТоваров
    Запрос=Новый Запрос;
    Запрос.Текст=
    "ВЫБРАТЬ
    |    ПартииТоваровОстатки.Номенклатура,
    |    ПартииТоваровОстатки.ДокументОприходования,
    |    ПартииТоваровОстатки.СрокГодности,
    |    ПартииТоваровОстатки.КоличествоОстаток КАК Количество,
    |    ПартииТоваровОстатки.СтоимостьОстаток КАК Стоимость
    |ИЗ
    |    РегистрНакопления.ПартииТоваров.Остатки(&Период, Номенклатура В (&Номенклатура)) КАК ПартииТоваровОстатки";
    Запрос.УстановитьПараметр("Период", Дата);
    Запрос.УстановитьПараметр("Номенклатура", Товары.ВыгрузитьКолонку("Номенклатура"));
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Результат=Запрос.Выполнить().Выгрузить();
    ТЧ=Товары.Выгрузить();
    ТЧ.Свернуть("Номенклатура", "Количество");
    Для Каждого ТекСтрока Из ТЧ Цикл
        КСписанию=ТекСтрока.Количество;
        Пока КСписанию>0 Цикл
            стр=НайтиСтрокуСписания(Результат, ТекСтрока.Номенклатура);
            Если стр=Неопределено Тогда
                Прервать;
            КонецЕсли;
            КСписанию=Мин(ТекСтрока.Количество, стр.Количество);
            
            Движение=Движения.ПартииТоваров.Добавить();
            Движение.Период=Дата;
            Движение.ВидДвижения=ВидДвиженияНакопления.Расход;
            Движение.Номенклатура=ТекСтрока.Номенклатура;
            Движение.ДокументОприходования=стр.ДокументОприходования;
            Движение.СрокГодности=стр.СрокГодности;
            Движение.Количество=Мин(ТекСтрока.Количество, стр.Количество);
            Движение.Стоимость=Движение.Количество*стр.Стоимость/стр.Количество;
            
            стр.Стоимость=(стр.Количество-КСписанию)*(стр.Стоимость/стр.Количество);
            стр.Количество=стр.Количество-КСписанию;
            КСписанию=ТекСтрока.Количество-Движение.Количество;
            ТекСтрока.Количество=КСписанию;
        КонецЦикла;
    КонецЦикла;
    Движения.ПартииТоваров.Записать();
КонецПроцедуры
17 makss89
 
16.04.14
14:53
скорость и количество строк
18 vicof
 
16.04.14
14:58
(17) Выделяешь всю процедуру обработкаПроведения и удаляешь ее. И количество строк и скорость оптимизируются :)
19 makss89
 
16.04.14
15:00
а если без шуток?
20 Wobland
 
16.04.14
15:01
(19) учиться надо
21 vicof
 
16.04.14
15:02
22 makss89
 
16.04.14
15:06
понятно что учится надо
23 makss89
 
16.04.14
15:07
Ну дак что значит никто не поможет?
24 vicof
 
16.04.14
15:07
(23) Сколько заплатишь?
25 Wobland
 
16.04.14
15:10
(23) говори прямо: надо сделать за тебя
26 makss89
 
16.04.14
15:11
я так и говорю в принципе
27 Wobland
 
16.04.14
15:13
а я ему ещё за кодом лазил.. 500 рублёв и я переделаю его под тебя
28 makss89
 
16.04.14
15:20
короче могли бы сразу написать что не поможете...там же не изначально писать надо а оптимизировать
29 katc
 
16.04.14
15:21
(16)
     |    Документ.РасходнаяНакладная.Товары КАК РасходнаяНакладнаяТовары
        |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваров.Остатки(&Период, Номенклатура В (&Номенклатура)) КАК ПартииТоваровОстатки
        |        ПО РасходнаяНакладнаяТовары.Номенклатура = ПартииТоваровОстатки.Номенклатура
        |ГДЕ
        |    РасходнаяНакладнаяТовары.Ссылка = &Ссылка

не стыдно?
30 Wobland
 
16.04.14
15:22
(28) ты нас ещё программировать поучи
31 vicof
 
16.04.14
15:22
(28) А ты думаешь, оптимизировать проще?
32 mistеr
 
16.04.14
15:22
(16) Товй код сломал мистовский парсер :)
33 floody
 
16.04.14
15:30
(29) за этот код и мне стыдно(
34 Wobland
 
16.04.14
15:32
(29) гы.. стыдно, да
35 Wobland
 
16.04.14
15:33
+(34) у меня ещё есть. то, что прошло экзамен
36 vicof
 
16.04.14
15:34
(35) Школьный по информатике?
37 Wobland
 
16.04.14
15:35
(36) обижаешь. жёлтенький ;)
38 katc
 
16.04.14
15:36
(35) ну желтенькими дипломами только туалеты оклеивать, да уборщиц удивлять.
39 ptiz
 
16.04.14
15:46
(21) Класс! Давно я не видел страниц с кривыми кодировками!
40 DexterMorgan
 
16.04.14
15:47
ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
    РеализацияТоваровУслугТовары.Характеристика КАК Характеристика,
    СУММА(РеализацияТоваровУслугТовары.Количество) КАК Количество
ПОМЕСТИТЬ ПодЗапрос
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ГДЕ
    РеализацияТоваровУслугТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугТовары.Номенклатура,
    РеализацияТоваровУслугТовары.Характеристика

ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Характеристика
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ПодЗапрос.Номенклатура,
    ПодЗапрос.Характеристика,
    ПодЗапрос.Количество КАК КоличествоПоДокументу,
    ЕСТЬNULL(ОстаткиТоваровКомпанииОстатки.КоличествоОстаток, 0) КАК КоличествоНаСкладе
ИЗ
    ПодЗапрос КАК ПодЗапрос
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(
                ,
                Склад = &Склад
                    И (Номенклатура, Характеристика) В
                        (ВЫБРАТЬ
                            ПодЗапрос.Номенклатура,
                            ПодЗапрос.Характеристика
                        ИЗ
                            ПодЗапрос КАК ПодЗапрос)) КАК ОстаткиТоваровКомпанииОстатки
        ПО (ОстаткиТоваровКомпанииОстатки.Номенклатура = ПодЗапрос.Номенклатура)
            И (ОстаткиТоваровКомпанииОстатки.Характеристика = ПодЗапрос.Характеристика)
41 vi0
 
16.04.14
15:49
(0) Склад - какое измерение по счету в регистре?
42 DexterMorgan
 
16.04.14
15:50
Запрос.УстановитьПараметр("ТекущийДокумент",     Ссылка);

Нужно заменить на

Запрос.УстановитьПараметр("Ссылка",     Ссылка);

=)
43 DexterMorgan
 
16.04.14
15:50
(41) Разве это важно? отбор на все поля же
44 Wobland
 
16.04.14
15:51
(38) мне пока не хватает на туалет. даже на самый маленьький
45 DexterMorgan
 
16.04.14
15:53
(41) хотя все же наверное лучше еще пакет добавить куда поместить остатки, с отбором по складу
46 Maxus43
 
16.04.14
15:54
ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
    РеализацияТоваровУслугТовары.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    РеализацияТоваровУслугТовары.Ссылка.Склад КАК Склад
ПОМЕСТИТЬ втРеализация
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ГДЕ
    РеализацияТоваровУслугТовары.Ссылка = &Ссылка

ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    ХарактеристикаНоменклатуры,
    Склад
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    втРеализация.Номенклатура,
    втРеализация.ХарактеристикаНоменклатуры,
    ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
    втРеализация КАК втРеализация
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Моменто, ) КАК ТоварыНаСкладахОстатки
        ПО втРеализация.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
            И втРеализация.ХарактеристикаНоменклатуры = ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры
            И втРеализация.Склад = ТоварыНаСкладахОстатки.Склад

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("Моменто", Ссылка.Дата);
47 Wobland
 
16.04.14
15:54
(45) на зачем?
48 DexterMorgan
 
16.04.14
15:56
ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
    РеализацияТоваровУслугТовары.Характеристика КАК Характеристика,
    СУММА(РеализацияТоваровУслугТовары.Количество) КАК Количество
ПОМЕСТИТЬ ПодЗапрос
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ГДЕ
    РеализацияТоваровУслугТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугТовары.Номенклатура,
    РеализацияТоваровУслугТовары.Характеристика

ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Характеристика
;

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

ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Характеристика
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ПодЗапрос.Номенклатура,
    ПодЗапрос.Характеристика,
    ПодЗапрос.Количество КАК КоличествоВДокументе,
    ЕСТЬNULL(Остатки.КоличествоНаСкладе, 0) КАК КоличествоНаСкладе
ИЗ
    ПодЗапрос КАК ПодЗапрос
        ЛЕВОЕ СОЕДИНЕНИЕ Остатки КАК Остатки
        ПО ПодЗапрос.Номенклатура = Остатки.Номенклатура
            И ПодЗапрос.Характеристика = Остатки.Характеристика
49 vi0
 
16.04.14
15:57
(43) я к тому, что там может быть еще к.н. измерение
50 DexterMorgan
 
16.04.14
15:58
(47) Оптимизатору СУБД чтобы выбрать наиболее оптимальный план нужно знать сколько записей в таблицах которые он соединяет, вирт таблица возможно будет транслироваться во вложенный запрос, в котором не понятно сколько записей
51 Wobland
 
16.04.14
15:59
(50) ну это уже перебор - такой фигнёй страдать
52 DexterMorgan
 
16.04.14
16:00
(49) Как ты повлияешь на это не меняя конфигурацию?
53 DexterMorgan
 
16.04.14
16:01
(51) Я и не страдал, пока запросы к базе >400Гб не стал писать =)
54 Maxus43
 
16.04.14
16:04
(50) только вот дополнительно дёргать в ВТ все остатки по складу с 500 тысячами наименований - более чем не разумно имхо
55 vi0
 
16.04.14
16:05
(52) вам должно быть стыдно задавать такие вопросы)
56 Maxus43
 
16.04.14
16:05
(54) + упс, отбор по номенклатуре не засёк
57 DexterMorgan
 
16.04.14
16:14
(56) ну по характеристике и складу тож отбор идет

(55) поясни, пожалуйста. я знаю что порядок измерений влияет на это, что не должно быть пропусков по отбору, но изменить порядок можно же только изменив конфу
58 vi0
 
16.04.14
16:15
(57) к примеру там есть измерения по организации и если есть возможноть задать отбор по нему то лучше задать
59 DexterMorgan
 
16.04.14
16:15
(58) а ну это понятно =)
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс