Имя: Пароль:
1C
1С v8
Как оптимизировать запрос к реальным таблицам?
0 ИС-2
 
naïve
23.09.13
15:25
Вот фрагмент запроса из отчета на СКД. С включенными отборами отчет выполняется достаточно быстро. Но надо еще его ускорить т.к он будет использоваться при проведении, вызываться из КПК и т.д (ручной вывод в таблицу значений).
Пробывал помещать реальную таблицу взаимрасчетов во временную - привело к падению производительности.
За счет чего можно ускорить? Запрос доработан, чтобы открывался в типовых

       ВЫБРАТЬ
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК ДатаКалендаря,
    РегламентированныйПроизводственныйКалендарь.Год,
    РегламентированныйПроизводственныйКалендарь.ВидДня,
    1 КАК КоличествоДней
ПОМЕСТИТЬ ВТ_Календарь
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
    (РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
            ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
    И РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ ДОБАВИТЬКДАТЕ(&ДатаОтчета, ДЕНЬ, -365) И &ДатаОтчета

ИНДЕКСИРОВАТЬ ПО
    ДатаКалендаря
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Запрос_Дебеторка.ДоговорКонтрагента,
    Запрос_Дебеторка.РасчетнаяДата,
    Запрос_Дебеторка.РасчетныйДокумент,
    Запрос_Дебеторка.СуммаОстатокВВалютеВзаиморасчетов,
    СУММА(ВТ_Календарь.КоличествоДней) КАК КоличествоДней,
    Запрос_Дебеторка.Контрагент
ПОМЕСТИТЬ ВТ_Дебеторка
ИЗ
    (ВЫБРАТЬ
        Остатки.ДоговорКонтрагента КАК ДоговорКонтрагента,
        ОсновнаяТаблицаРегистра.Период КАК РасчетнаяДата,
        ОсновнаяТаблицаРегистра.Регистратор КАК РасчетныйДокумент,
        ВЫБОР
            КОГДА СУММА(ТаблицаПоследующихПриходов.СуммаВзаиморасчетов * ВЫБОР
                        КОГДА ТаблицаПоследующихПриходов.ВидДвижения = &ВидДвиженияПриход
                                И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов > 0
                                И ТаблицаПоследующихПриходов.Регистратор <> ОсновнаяТаблицаРегистра.Регистратор
                            ТОГДА 1
                        КОГДА ТаблицаПоследующихПриходов.ВидДвижения <> &ВидДвиженияПриход
                                И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов < 0
                                И ТаблицаПоследующихПриходов.Регистратор <> ОсновнаяТаблицаРегистра.Регистратор
                            ТОГДА -1
                        ИНАЧЕ 0
                    КОНЕЦ) > Остатки.СуммаВзаиморасчетовОстаток
                ТОГДА 0
            ИНАЧЕ ВЫБОР
                    КОГДА СУММА(ТаблицаПоследующихПриходов.СуммаВзаиморасчетов * ВЫБОР
                                КОГДА ТаблицаПоследующихПриходов.ВидДвижения = &ВидДвиженияПриход
                                        И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов > 0
                                    ТОГДА 1
                                КОГДА ТаблицаПоследующихПриходов.ВидДвижения <> &ВидДвиженияПриход
                                        И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов < 0
                                    ТОГДА -1
                                ИНАЧЕ 0
                            КОНЕЦ) > Остатки.СуммаВзаиморасчетовОстаток
                        ТОГДА СУММА(ВЫБОР
                                    КОГДА ОсновнаяТаблицаРегистра.Регистратор = ТаблицаПоследующихПриходов.Регистратор
                                        ТОГДА Остатки.СуммаВзаиморасчетовОстаток
                                    ИНАЧЕ 0
                                КОНЕЦ) - СУММА(ТаблицаПоследующихПриходов.СуммаВзаиморасчетов * ВЫБОР
                                    КОГДА ТаблицаПоследующихПриходов.ВидДвижения = &ВидДвиженияПриход
                                            И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов > 0
                                            И ОсновнаяТаблицаРегистра.Регистратор <> ТаблицаПоследующихПриходов.Регистратор
                                        ТОГДА 1
                                    КОГДА ТаблицаПоследующихПриходов.ВидДвижения <> &ВидДвиженияПриход
                                            И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов < 0
                                            И ОсновнаяТаблицаРегистра.Регистратор <> ТаблицаПоследующихПриходов.Регистратор
                                        ТОГДА -1
                                    ИНАЧЕ 0
                                КОНЕЦ)
                    ИНАЧЕ СУММА(ОсновнаяТаблицаРегистра.СуммаВзаиморасчетов * ВЫБОР
                                КОГДА ОсновнаяТаблицаРегистра.ВидДвижения = &ВидДвиженияПриход
                                        И ОсновнаяТаблицаРегистра.СуммаВзаиморасчетов > 0
                                        И ОсновнаяТаблицаРегистра.Регистратор = ТаблицаПоследующихПриходов.Регистратор
                                    ТОГДА 1
                                КОГДА ОсновнаяТаблицаРегистра.ВидДвижения <> &ВидДвиженияПриход
                                        И ОсновнаяТаблицаРегистра.СуммаВзаиморасчетов < 0
                                        И ОсновнаяТаблицаРегистра.Регистратор = ТаблицаПоследующихПриходов.Регистратор
                                    ТОГДА -1
                                ИНАЧЕ 0
                            КОНЕЦ)
                КОНЕЦ
        КОНЕЦ КАК СуммаОстатокВВалютеВзаиморасчетов,
        Остатки.ДоговорКонтрагента.Владелец КАК Контрагент
    ИЗ
        РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&ДатаОтчета) КАК Остатки
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                ВзаиморасчетыСКонтрагентами.ДоговорКонтрагента КАК ДоговорКонтрагента,
                ВзаиморасчетыСКонтрагентами.Период КАК Период,
                ВзаиморасчетыСКонтрагентами.Регистратор КАК Регистратор,
                ВзаиморасчетыСКонтрагентами.ВидДвижения КАК ВидДвижения,
                СУММА(ВзаиморасчетыСКонтрагентами.СуммаВзаиморасчетов) КАК СуммаВзаиморасчетов
            ИЗ
                РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК ВзаиморасчетыСКонтрагентами
            
            СГРУППИРОВАТЬ ПО
                ВзаиморасчетыСКонтрагентами.ДоговорКонтрагента,
                ВзаиморасчетыСКонтрагентами.Период,
                ВзаиморасчетыСКонтрагентами.Регистратор,
                ВзаиморасчетыСКонтрагентами.ВидДвижения) КАК ОсновнаяТаблицаРегистра
                ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                    ВзаиморасчетыСКонтрагентами.ДоговорКонтрагента КАК ДоговорКонтрагента,
                    ВзаиморасчетыСКонтрагентами.Период КАК Период,
                    ВзаиморасчетыСКонтрагентами.Регистратор КАК Регистратор,
                    ВзаиморасчетыСКонтрагентами.ВидДвижения КАК ВидДвижения,
                    СУММА(ВзаиморасчетыСКонтрагентами.СуммаВзаиморасчетов) КАК СуммаВзаиморасчетов
                ИЗ
                    РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК ВзаиморасчетыСКонтрагентами
                
                СГРУППИРОВАТЬ ПО
                    ВзаиморасчетыСКонтрагентами.ДоговорКонтрагента,
                    ВзаиморасчетыСКонтрагентами.Период,
                    ВзаиморасчетыСКонтрагентами.Регистратор,
                    ВзаиморасчетыСКонтрагентами.ВидДвижения) КАК ТаблицаПоследующихПриходов
                ПО (ТаблицаПоследующихПриходов.ДоговорКонтрагента = ОсновнаяТаблицаРегистра.ДоговорКонтрагента)
                    И (ТаблицаПоследующихПриходов.Период > ОсновнаяТаблицаРегистра.Период
                        ИЛИ ТаблицаПоследующихПриходов.Период = ОсновнаяТаблицаРегистра.Период
                            И ТаблицаПоследующихПриходов.Регистратор >= ОсновнаяТаблицаРегистра.Регистратор)
                    И (ТаблицаПоследующихПриходов.Период <= &ДатаОтчета)
                    И (ТаблицаПоследующихПриходов.ВидДвижения = &ВидДвиженияПриход
                            И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов > 0
                        ИЛИ ТаблицаПоследующихПриходов.ВидДвижения <> &ВидДвиженияПриход
                            И ТаблицаПоследующихПриходов.СуммаВзаиморасчетов < 0)
            ПО Остатки.ДоговорКонтрагента = ОсновнаяТаблицаРегистра.ДоговорКонтрагента
                И (ОсновнаяТаблицаРегистра.Период <= &ДатаОтчета)
                И (ОсновнаяТаблицаРегистра.ВидДвижения = &ВидДвиженияПриход
                        И ОсновнаяТаблицаРегистра.СуммаВзаиморасчетов > 0
                    ИЛИ ОсновнаяТаблицаРегистра.ВидДвижения <> &ВидДвиженияПриход
                        И ОсновнаяТаблицаРегистра.СуммаВзаиморасчетов < 0)
    ГДЕ
        Остатки.СуммаВзаиморасчетовОстаток > 0
    
    СГРУППИРОВАТЬ ПО
        Остатки.ДоговорКонтрагента,
        ОсновнаяТаблицаРегистра.Период,
        ОсновнаяТаблицаРегистра.Регистратор,
        Остатки.СуммаВзаиморасчетовОстаток,
        Остатки.ДоговорКонтрагента.Владелец) КАК Запрос_Дебеторка
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Календарь КАК ВТ_Календарь
        ПО (НЕ Запрос_Дебеторка.СуммаОстатокВВалютеВзаиморасчетов = 0)
            И (ВТ_Календарь.ДатаКалендаря < &ДатаОтчета)
            И (ВТ_Календарь.ДатаКалендаря >= НАЧАЛОПЕРИОДА(Запрос_Дебеторка.РасчетнаяДата, ДЕНЬ))

СГРУППИРОВАТЬ ПО
    Запрос_Дебеторка.ДоговорКонтрагента,
    Запрос_Дебеторка.РасчетнаяДата,
    Запрос_Дебеторка.РасчетныйДокумент,
    Запрос_Дебеторка.СуммаОстатокВВалютеВзаиморасчетов,
    Запрос_Дебеторка.Контрагент
;
1 Maxus43
 
23.09.13
15:47
ИЛИ в соединениях по разным реквизитам зло...
перегружен запрос вложенными, они тоже не всегда хороши, может привести к выбору неверно плана запроса
2 ИС-2
 
naïve
23.09.13
15:56
(1) про ИЛИ в курсе, но его оставлю на потом
3 Maxus43
 
23.09.13
15:57
Разбивай запрос на куски, т.е. свои вложенные выполняй отдельно, смотри скорость, иди снизу вверх короче
4 Kreont
 
23.09.13
16:00
(0) добавь обязательно индексы для нужн.полей по ВТ, скорость в N-раз возрастет.
5 ИС-2
 
naïve
23.09.13
16:04
(3) в моем случае это будет неочень корректно т.к результат запроса будет получаться через СКД,а не через запрос т.е финальный запрос будет другим. И тут вопрос больше упирается в теорию.
(4) попробую еще раз вынести во временную таблицу с индексами, но думаю эффекта не даст
6 Maxus43
 
23.09.13
16:05
(5) на куски разбивать - всмысле в консоли запросов, чтоб понять где тормозит не на этой портянке, а на обозримом простым взгялом запросе, и тут уже подключать теорию
7 ИС-2
 
naïve
25.09.13
16:03
временные таблицы дали эффект. Думаю процентов на 20%
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.