Имя: Пароль:
1C
1С v8
Запрос. Есть идеи как можно ускорить?
0 Галахад
 
гуру
19.03.13
10:25
На локальной машине выполняется 0,5 сек., по сети 5,5 сек.


ВЫБРАТЬ РАЗРЕШЕННЫЕ
   РегПороги.ЗначениеПорога КАК ЗначениеПорога
ИЗ
   (ВЫБРАТЬ
       ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
   ИЗ
       РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(&ДатаНач, &ДатаКон, , ДисконтнаяКарта = &ДисконтнаяКарта) КАК РегПродажи) КАК РегПродажи
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
           Пороги.НижняяГраница КАК НижняяГраница,
           Пороги.ЗначениеПорога КАК ЗначениеПорога
       ИЗ
           РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК Пороги
               ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                   МАКСИМУМ(ПорогиМакс.Период) КАК Период
               ИЗ
                   РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК ПорогиМакс) КАК ПорогиМакс
               ПО Пороги.Период = ПорогиМакс.Период) КАК РегПороги
       ПО (РегПороги.НижняяГраница <= РегПродажи.СуммаОборот)
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
           МАКСИМУМ(РегПороги.НижняяГраница) КАК НижняяГраница
       ИЗ
           (ВЫБРАТЬ
               ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
           ИЗ
               РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(&ДатаНач, &ДатаКон, , ДисконтнаяКарта = &ДисконтнаяКарта) КАК РегПродажи) КАК РегПродажи
               ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                   Пороги.НижняяГраница КАК НижняяГраница
               ИЗ
                   РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК Пороги
                       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                           МАКСИМУМ(ПорогиМакс.Период) КАК Период
                       ИЗ
                           РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК ПорогиМакс) КАК ПорогиМакс
                       ПО Пороги.Период = ПорогиМакс.Период) КАК РегПороги
               ПО (РегПороги.НижняяГраница <= РегПродажи.СуммаОборот)) КАК РегПорогиМакс
       ПО (РегПорогиМакс.НижняяГраница = РегПороги.НижняяГраница)
1 Defender aka LINN
 
19.03.13
10:26
Соединение с вложенными запросами - не айс
2 andreymongol82
 
19.03.13
10:27
Много вложеных запросов и вдобавок в соединении. Как бэ не рекомендуется.
3 H A D G E H O G s
 
19.03.13
10:33
Поменять профессию. Срочно.
4 Галахад
 
гуру
19.03.13
10:34
(1), (2) Угу.

(3) Чего это?
5 acsent
 
19.03.13
10:34
зачем вот это вот
ВЫБРАТЬ
 МАКСИМУМ(ПорогиМакс.Период) КАК Период
ИЗ
РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, )
6 Лефмихалыч
 
19.03.13
10:41
(1) +100500
(3) +50250
7 andreymongol82
 
19.03.13
10:52
Какая все-таки красота.
Прям как по учебнику, точнее по методическим рекомендациям :)
Сегодня с утра разбирал подобное :)

1.1 При написании запросов не следует использовать соединения с вложенными запросами. Следует соединять друг с другом только объекты метаданных или временные таблицы. Если запрос использует соединения с вложенными запросами, то его следует переписать с использованием временных таблиц (не важно с какой стороны соединения находится вложенный запрос).

Если запрос содержит соединения с вложенными запросами, то это может привести к следующим негативным последствиям:

   Крайне медленное выполнение запроса при слабой загрузке серверного оборудования. Замедление запроса может быть очень значительным (до нескольких порядков).
   Нестабильная работа запроса. При некоторых условиях запрос может работать достаточно быстро, при других - очень медленно.
   Значительная разница по времени выполнения запроса на разных СУБД.
   Повышенная чувствительность запроса к актуальности и полноте статистик. Сразу после полного обновления статистик запрос может работать быстро, но через некоторое время опять замедлиться.

Пример потенциально опасного запроса, использующего соединение с вложенным запросом:
Копировать в буфер обмена

ВЫБРАТЬ ...
ИЗ Документ.РеализацияТоваровУслуг
ЛЕВОЕ СОЕДИНЕНИЕ (
  ВЫБРАТЬ ИЗ РегистрСведений.Лимиты
  ГДЕ ...
  СГРУППИРОВАТЬ ПО ...
) ПО ...
8 MaxisUssr
 
19.03.13
10:57
(0)
Для того, чтобы быстро работало на всех (любых) серваках, придется все вложенные запросы переписать на временные таблицы. Сам напарывался и не раз - в итоге это значительно помогло.
9 Галахад
 
гуру
19.03.13
10:58
Уважаемые, вы это Борису Георгиевичу передавайте.

Код в (0) из типовой.
10 MaxisUssr
 
19.03.13
10:58
Вообще вложенные запросы - удобная вещь, но, похоже, оптимизатор (или транслятор текста запроса из 1С в SQL) их не любит
11 Галахад
 
гуру
19.03.13
10:58
(8) Угу.
12 Галахад
 
гуру
19.03.13
10:59
(10) На SQL этот запрос 0,03 сек. выполняется.
13 MaxisUssr
 
19.03.13
11:00
(12)
В смысле "этот запрос"? Ты написал такой же запрос на SQL и запустил его, или же посмотрел, как представленный в (0) запрос 1С преобразовала в SQL и использовал его?
14 Галахад
 
гуру
19.03.13
11:03
В файловой базе локально 0,5 сек.
В файловой базе по сети 5,5 сек.
На SQL базе локально 0,03.
15 H A D G E H O G s
 
19.03.13
11:05
(14) А на "холодном" SQL скока? :-)
16 andreymongol82
 
19.03.13
11:06
(14) А если без собранной статистики на SQL?
17 Галахад
 
гуру
19.03.13
11:07
(15) Что значит "холодном"? На свежей копии базы?
18 H A D G E H O G s
 
19.03.13
11:07
(16) Ну это незачет. Статистику и обновить можно достаточно часто.
19 H A D G E H O G s
 
19.03.13
11:11
(17) "На SQL базе локально 0,03."

Это прям после перезапуска SQL сервера 0.03 секунды, или после того, как несколько раз этот запрос уже запускали?
20 MaxisUssr
 
19.03.13
11:12
(19)
Да, кстати, если перезапустить сервак - сколько займет времени выполнение запроса по сети?
21 Галахад
 
гуру
19.03.13
11:16
(19) Не. SQL месяца два не перезагружался.

(20) Не знаю. Нету у меня под боком тестового сервера.
А рабочий я перегружать не собираюсь. :-)
22 H A D G E H O G s
 
19.03.13
11:18
(21) Сделай тестовый, че не так то?
23 Галахад
 
гуру
19.03.13
11:19
(22) Я лучше запрос (0) поковыряю.
24 andreymongol82
 
19.03.13
11:24
(18) Это один из элементов проверки "на холодный" SQL. Особенно, если низя перезагружать. (23) Действительно, лучше запрос поковырять :)
25 kiruha
 
19.03.13
11:30
(17)
"На SQL базе локально 0,03."
Чтобы только перевести с языка 1С на SQL нужно больше

У тебя возвращается кэширумый результат

По (0) не стоит никаких внутренних отборов
если ртборы не нужны - типа отчет - нет никаких проблем в 5 сек
26 kiruha
 
19.03.13
11:42
(2)
>>Много вложеных запросов и вдобавок в соединении. Как бэ не рекомендуется.<<

один товарищ в книжке написал - другие повторяют
1С сервер почти любой запрос преобразует в множество вложенных. Для бухии их может быть с десяток.
Еще парочка никаким кардинальным образом на скорость не влияет, если нет индексов в соединении
27 Галахад
 
гуру
19.03.13
11:44
(25) Вот же параметры:

&ДатаНач
&ДатаКон
&ДисконтнаяКарта
28 andreymongol82
 
19.03.13
11:49
(26) Да ладно. А какой запрос на скл будет быстрее к временной таблице или к реальной как в приведенном выше.
29 kiruha
 
19.03.13
11:53
(28)
Проверяется элементарно
Возьмите запрос из 0. Вставьте в
Выбрать * Из (ЗапросИз0) Как запросИз0

сделайте замер что было и что стало
Если разница будет больше нескольких процентов - Вы правы
30 andreymongol82
 
19.03.13
11:59
(29) Нет. Не так. Проверить можно переделав вложенные запросы в соединении на временные таблицы. А предложенный способ некорректен, так как последняя, самая верхняя выборка будет выборкой из выборки.
31 H A D G E H O G s
 
19.03.13
12:00
(26) Бугага.
Убейте себя ап стену.

(28)

Проблема временных таблиц - не во времени выборки из них, а во времени вставки в них.
32 H A D G E H O G s
 
19.03.13
12:01
(28) Вот когда Сервер 1С будет поддерживать #table объекты (с сохранением поддержки временных таблиц) и программисты 1С будут знать, что лучше пользовать - будет щасте.
33 andreymongol82
 
19.03.13
12:03
(32) Я молюсь об этом раз в неделю. Может надо каждый день? (31) Ога, во вставке, однако по сумме времени по всему запросу получается чуть быстрее
34 kiruha
 
19.03.13
12:03
ВЫБРАТЬ
                           МАКСИМУМ(ПорогиМакс.Период) КАК Период
                       ИЗ
                           РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, )

это что то
Шерстить все 2 таблицы чтобы получить максимум периода, и без измерений....
Здесь оптимальнее к реальной таблице
35 H A D G E H O G s
 
19.03.13
12:03
В все равно - все виртуальные таблицы, помещенные во временные и не дублированные (а у автора есть и они, дубли) - дадут нехилый прирост во времени и план запроса не будет напоминать бурелом после бури. А уж если RLS...
36 andreymongol82
 
19.03.13
12:05
(34) Кстати, да
(35) Тока хотел про дубли написать
37 GANR
 
19.03.13
12:06
Имхо, это

ВЫБРАТЬ
ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
ИЗ РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(&ДатаНач, &ДатаКон, , ДисконтнаяКарта = &ДисконтнаяКарта) КАК РегПродажи

должно быть во временной таблице, а не читаться каждый раз
38 GANR
 
19.03.13
12:17
+(37) А что? Для этой ВТ, проблема (31) будет небольшая (1 строчка), а количество чтений уменьшится.
39 Галахад
 
гуру
19.03.13
12:31
(37) Ага. Минимальное вмешательство.

ВЫБРАТЬ
   ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
ПОМЕСТИТЬ тзСуммаОборот
ИЗ
   РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(&ДатаНач, &ДатаКон, , ДисконтнаяКарта = &ДисконтнаяКарта) КАК РегПродажи
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   РегПороги.ЗначениеПорога КАК ЗначениеПорога
ИЗ
   (ВЫБРАТЬ
       ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
   ИЗ
       тзСуммаОборот КАК РегПродажи) КАК РегПродажи
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
           Пороги.НижняяГраница КАК НижняяГраница,
           Пороги.ЗначениеПорога КАК ЗначениеПорога
       ИЗ
           РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК Пороги
               ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                   МАКСИМУМ(ПорогиМакс.Период) КАК Период
               ИЗ
                   РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК ПорогиМакс) КАК ПорогиМакс
               ПО Пороги.Период = ПорогиМакс.Период) КАК РегПороги
       ПО (РегПороги.НижняяГраница <= РегПродажи.СуммаОборот)
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
           МАКСИМУМ(РегПороги.НижняяГраница) КАК НижняяГраница
       ИЗ
           (ВЫБРАТЬ
               ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
           ИЗ
               тзСуммаОборот КАК РегПродажи) КАК РегПродажи
               ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                   Пороги.НижняяГраница КАК НижняяГраница
               ИЗ
                   РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК Пороги
                       ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                           МАКСИМУМ(ПорогиМакс.Период) КАК Период
                       ИЗ
                           РегистрСведений.ПорогиНакопительныхСкидок.СрезПоследних(&ДатаКон, ) КАК ПорогиМакс) КАК ПорогиМакс
                       ПО Пороги.Период = ПорогиМакс.Период) КАК РегПороги
               ПО (РегПороги.НижняяГраница <= РегПродажи.СуммаОборот)) КАК РегПорогиМакс
       ПО (РегПорогиМакс.НижняяГраница = РегПороги.НижняяГраница)
40 Галахад
 
гуру
19.03.13
12:34
Локально на файловой запрос из (39) выполняется ,157

А этот запрос ниже 0,141

ВЫБРАТЬ
       ЕСТЬNULL(СУММА(РегПродажи.СуммаОборот), 0) КАК СуммаОборот
   ИЗ
       РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(&ДатаНач, &ДатаКон, , ДисконтнаяКарта = &ДисконтнаяКарта) КАК РегПродажи
41 GANR
 
19.03.13
12:53
(40) Вообще, при соединении с вложенным запросом оптимизатор СУБД с какого-то перепугу может решить, что его лучше выполнять в цикле. Это из книги "Профессиональная разработка  в системе 1С:Предприятие 8".
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.