Имя: Пароль:
1C
1С v8
Оптимизация запроса
,
0 goodjob
 
06.03.13
13:57
Какой запрос более оптимален.
Что лучше, выбрать 1 раз из виртуальной таблицы и использовать "ВЫБОР КОГДА ТОГДА" или выбрать несколько раз из виртуальных таблиц и НЕ использовать "ВЫБОР КОГДА ТОГДА"

1)
ВЫБРАТЬ
  Субконто1,
  ВЫБОР КОГДА Счет = &Счет1 ТОГДА СуммаОборотКт ИНАЧЕ 0 КОНЕЦ КАК Сумма1,
  ВЫБОР КОГДА Счет = &Счет2 ТОГДА СуммаОборотКт ИНАЧЕ 0 КОНЕЦ КАК Сумма2
ИЗ
  РегистрБухгалтерии.Хозрасчетный.Обороты(,,,Счет В (&Счет1,&Счет2))

или:

2)
ВЫБРАТЬ
  Субконто1,
  Сумма(Сумма1) КАК Сумма1,
  Сумма(Сумма2) КАК Сумма2
ИЗ(
  ВЫБРАТЬ
     Субконто1,
     СуммаОборотКт КАК Сумма1,
     0 КАК Сумма2
  ИЗ
     РегистрБухгалтерии.Хозрасчетный.Обороты(,,,Счет = &Счет1)

  ОБЪЕДИНИТЬ ВСЕ

  ВЫБРАТЬ
     Субконто1,
     0 КАК Сумма1,
     СуммаОборотКт КАК Сумма2
  ИЗ
     РегистрБухгалтерии.Хозрасчетный.Обороты(,,,Счет = &Счет2)
) КАК Обороты
СГРУППИРОЫВТЬ ПО Субконто1
1 Rie
 
06.03.13
13:59
(0) Всяко вариант 1 лучше.
2 goodjob
 
06.03.13
14:01
(1) Чем?
3 mikecool
 
06.03.13
14:02
(0) замер производительности не предлагать?
4 ДенисЧ
 
06.03.13
14:03
(2) чем второй...
5 Defender aka LINN
 
06.03.13
14:03
(2) Тем, что запрос один а не два, не?
6 mikecool
 
06.03.13
14:04
(5) я бы без замеорв не был бы так категоричен
7 goodjob
 
06.03.13
14:05
(3) Ты прав. Надо мерить. Но если у кого то есть теоретическое обоснование - напишите, пожалуйста.
8 mikecool
 
06.03.13
14:07
(7) теория не всегда совпадает с практикой, так что - меряй.
9 RomanYS
 
06.03.13
14:13
(0) почему СГРУППИРОВАТЬ только во втором запросе?
10 Maxus43
 
06.03.13
14:15
(9) потому что в первом уже сгруппировано
11 RomanYS
 
06.03.13
14:17
(10) с чего это вдруг?
12 Fragster
 
гуру
06.03.13
14:18
(10) а если субконто одинаковые у счетов?
13 Aprobator
 
06.03.13
14:21
(6) да ладно. То  ты один раз прошелся по данным и условие проверил, а то два, сначала для первого условия, потом для второго.
14 Maxus43
 
06.03.13
14:21
(11)(12) да, для чистоты надо добавить.
2 записи с одним субконто и одним счетом - сами схлопнутся, а вот разные счета нет...
15 goodjob
 
06.03.13
14:25
(9) да, надо тоже добавить группировку
16 Rie
 
06.03.13
14:31
(7) Ты во втором варианте создаёшь две больших таблицы. Потом их объединяешь... Ну зачем это?
17 goodjob
 
06.03.13
14:31
Результат:

1-й запрос: 51,7 % времени
2-й запрос: 48,3 % времени

И это еще без группировки. Сейчас добавлю группировку, разница еще больше будет...
18 sapphire
 
06.03.13
14:32
Спор ни о чем.
Достаточно посмотреть во что вырождается первый и второй запрос.
19 RomanYS
 
06.03.13
14:34
(17) при одинаковой производительности я бы оставил более чиаемый вариант, т.е. первый
20 goodjob
 
06.03.13
14:38
(18) Что ты имеешь ввиду? План запроса?
21 sapphire
 
06.03.13
14:39
(20) То, что поедет на сервер СУБД.
22 GANR
 
06.03.13
14:39
(0) Вариант ОБЪЕДИНИТЬ ВСЕ - это повторное сканирование таблицы, а считывание данных - тяжелее, чем ВЫБОР КОГДА.
23 sapphire
 
06.03.13
14:40
(20) И только потом смотреть план выполнения :)
24 goodjob
 
06.03.13
14:44
Результат с группировкой первого запроса:
1-й запрос: 56 % времени
2-й запрос: 44 % времени
25 Эстет хренов
 
06.03.13
14:45
(0) "Счет В (&Счет1,&Счет2)" почему не ИЛИ ?
26 goodjob
 
06.03.13
14:45
(22) похоже зависит от количества обрабатываемых строк. В моем случае "ВЫБОР КОГДА" тяжелее
27 goodjob
 
06.03.13
14:47
(21) а как увидеть то, что поедет на сервер СУБД?
28 goodjob
 
06.03.13
14:54
(25) Если не ошибаюсь, ИЛИ в SQL преобразуются в объединения... или соединения... В общем ИЛИ будет хуже.
29 sapphire
 
06.03.13
14:54
(27) Настроить технологический журнал или разбирать файл трассы...
30 sapphire
 
06.03.13
14:55
(25) При ИЛИ не работает индекс.
31 unregistered
 
06.03.13
14:56
К слову, если Счет1 и Счет2 имеют разное количество субконто (на одном, например - одно, а на втором - два), то запрос к СУБД всё равно выродиться в запрос к двум таблицам - остатков и оборотов по счетам с одним субконто и к таблице остатков и оборотов по счетам с двумя субконто.

И почему не рассматривается вопрос с соединением:

ВЫБРАТЬ
  ЕСТЬNULL(ХозрасчетныйОборотыПоСчету1.Субконто1, ХозрасчетныйОборотыПоСчету2.Субконто1) КАК Субконто,
  ЕСТЬNULL(ХозрасчетныйОборотыПоСчету1.СуммаОборотКт, 0) КАК Сумма1,
  ЕСТЬNULL(ХозрасчетныйОборотыПоСчету2.ВалютнаяСуммаОборотКт, 0) КАК Сумма2
ИЗ
  РегистрБухгалтерии.Хозрасчетный.Обороты(, , , Счет = &Счет1, , , , ) КАК ХозрасчетныйОборотыПоСчету1
  ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Обороты(, , , Счет = &Счет2, , , , ) КАК ХозрасчетныйОборотыПоСчету2
    ПО ХозрасчетныйОборотыПоСчету1.Субконто1 = ХозрасчетныйОборотыПоСчету2.Субконто1
УПОРЯДОЧИТЬ ПО
  Субконто
32 unregistered
 
06.03.13
14:57
(31) * ВалютнаяСуммаОборотКт читать как СуммаОборотКт
33 unregistered
 
06.03.13
15:01
(31)* вместо ЛЕВОГО соединения ПОЛНОЕ

Что-то туплю сегодня...
34 Эстет хренов
 
06.03.13
15:03
(30) действительно? это скверно, я так часто разворачиваю.
goodjob, запусти первый запрос с ИЛИ, скинь пожалуйста результат.
еще если не затруднит скинь релиз 1c, и к-во строк результата, спасибо.
35 goodjob
 
06.03.13
15:05
(31) таких счетов в запросе будет много, я для простоты взял два.
36 МихаилМ
 
06.03.13
15:09
для оборотов лучше указывать виды субконто.
37 unregistered
 
06.03.13
15:11
(35) Вы там часом не анализ субконто строите?

Тогда проще указать параметры виртуальной таблицы по виду субконто, выбирать в запросе одну сумму (вместо Сумма1, Сумма2,... СуммаN) и добавить в выбору поле Счет.
38 unregistered
 
06.03.13
15:14
+ к (37) Озвучил бы автор задачу целиком. А то может статься, что правильное решение не имеет ни чего общего с тем, что написано в (0)...
39 goodjob
 
06.03.13
15:27
(38) Это специализированный отчет по контрагентам и договорам, в нем много показателей которые представляют из себя обороты по определенным бух. счетам. Каждый показатель - один или несколько счетов. В основном у счетов Субконто1-Контрагент, Субконто2-Договор, но не у всех.
40 unregistered
 
06.03.13
15:40
(39) >> но не у всех.

Не у всех они идут в указанном порядке или не у всех они в принципе есть?

>> Это специализированный отчет

Ну и делайте на СКД. Всё одним запросом с полями Счет, Контрагент, Договор, СуммаОборота.
В настройках схемы в строках - контрагенты и договоры, в колонках - счета.
Если хочется красоты, то можно поле Счет заменить на поле Показатель

ВЫБОР
 КОГДА Счет = &Счет1 ТОГДА "Показатель1"
 КОГДА Счет = &Счет2 ТОГДА "Показатель2"
 КОГДА Счет В (&Счет3, &Счет4, &Счет5) ТОГДА "Показатель3"
КОНЕЦ КАК НазваниеПоказателя"
41 goodjob
 
06.03.13
15:55
(40) у некоторых порядок отличается, у некоторых нужно контрагента и договор вытаскивать из других мест.

Делаю на СКД. Там еще много вычисляемых полей на основе этих показателей, так что их надо иметь уже в запросе...
42 GANR
 
06.03.13
15:59
(0)(22) ВАЖНО! Счет В (&Счет1,&Счет2) это условие, скорее всего,   н е   и с п о л ь з у е т   индексы, в отличии от Счет = &Счет1 и Счет = &Счет2 во 2-м варианте. Вот поэтому 2-й вариант с ОБЪЕДИНИТЬ ВСЕ и 2-мя условиями использующими индексы быстрее... В стандартах 1С есть статья http://its.1c.ru/db/v8std#content:2149184307:1
43 GANR
 
06.03.13
16:00
(26) см. (42)
44 Fragster
 
гуру
06.03.13
16:01
(42) попутал ты что-то...
45 GANR
 
06.03.13
16:03
(44) Это из стандартов с ИТС. Например, запрос:

ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар ГДЕ Артикул = "001" ИЛИ Артикул = "002"  

следует заменить на запрос:  

ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар ГДЕ Артикул = "001"
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар ГДЕ Артикул = "002"
46 GANR
 
06.03.13
16:05
(44) как это Счет В (&Счет1,&Счет2) в профайлере отображается?
47 Fragster
 
гуру
06.03.13
16:11
Счет IN (@p1, @p2)
48 GANR
 
06.03.13
16:12
индекс при (47), вероятно НЕ работает, как и при (30)
49 sapphire
 
06.03.13
16:18
(22) Ну ты и отжег :))))
50 NicolayNN
 
06.03.13
16:37
(45) "Не следует использовать ИЛИ в секции ГДЕ". Про параметры виртуальной таблицы не сказано
51 Fragster
 
гуру
06.03.13
16:44
(48) ты на план запроса посмотрел?
52 Fragster
 
гуру
06.03.13
16:45
на ИТС за ИЛИ написано
53 GANR
 
06.03.13
16:46
(51) нет, с профайлером проблема
54 rs_trade
 
06.03.13
16:46
вообще затраты на выполнение case очень малы.
55 GANR
 
06.03.13
16:48
(52) Если (47) по индексу читает, то почему-же оно медленнее ОБЪЕДИНИТЬ ВСЕ ???
56 sapphire
 
06.03.13
16:50
(54) Не всегда так.
57 GANR
 
06.03.13
16:56
(49) С а м о е  смешное, что я когда-либо видел
Если СсылкаНаОбъект.ПолучитьОбъект().ЭтоНовый() Тогда
  ...
КонецЕсли;
58 rs_trade
 
06.03.13
17:05
что Счет IN (@p1, @p2), что объеденить, с большой долей вероятности сиквел эти два запроса приведет к одному виду
59 mikecool
 
06.03.13
17:11
(13) Александер, я же сказал, что не стал бы выносить однозначное решение без замеров производительности
60 rs_trade
 
06.03.13
17:14
+(59) Оптимизаторы СУБД не настолько тупы что бы два раза сканировать одни и те же данные в столь простом запросе.
61 Avalone2010
 
06.03.13
17:34
(0) Представьте что ваш код поддерживает сексуальный маньяк изврашенец, который знает где вы живете и какими тропами ходите домой. Я за первый вариант :)
62 goodjob
 
09.03.13
14:33
В итоге сделал так:


ВЫБРАТЬ
  Субконто1,
  СуммаОборотКт
ПОМЕСТИТЬ Обороты
ИЗ
  РегистрБухгалтерии.Хозрасчетный.Обороты(,,,Счет В (&Счет1,&Счет2))
ИНДЕКСИРОВАТЬ ПО Субконто1;

////////////////////////////////////////////////////////////

ВЫБРАТЬ
  Субконто1,
  Сумма(Сумма1) КАК Сумма1,
  Сумма(Сумма2) КАК Сумма2
ИЗ(
  ВЫБРАТЬ
     Субконто1,
     СуммаОборотКт КАК Сумма1,
     0 КАК Сумма2
  ИЗ
     Обороты ГДЕ Счет = &Счет1

  ОБЪЕДИНИТЬ ВСЕ

  ВЫБРАТЬ
     Субконто1,
     0 КАК Сумма1,
     СуммаОборотКт КАК Сумма2
  ИЗ
     Обороты ГДЕ Счет = &Счет2
) КАК Обороты
СГРУППИРОВАТЬ ПО Субконто1

И от "ВЫБРАТЬ КОГДА ТОГДА" избавился, и обращение к виртуальной таблице одно
63 Fragster
 
гуру
09.03.13
16:49
Индексироать не нужно
64 Fragster
 
гуру
09.03.13
16:49
если строк много - то не по СК, а по счету тогда уж
65 RomanYS
 
09.03.13
17:08
(62) это не может работать: ты в виртуальную таблицу счет не выбрал, а потом его в условиях используешь
66 goodjob
 
10.03.13
12:06
(64),(65) вы правы :)
67 Ksandr
 
10.03.13
13:07
(57) А самое печальное что я недавно встретил в конфе заказчика это:
Процедура УстановитьСубконто(Счет, Субконто, ВидСубконто, ЗначениеСубконто...)
...
Если ТипЗнч(ВидСубконто) = Тип("Число") Тогда
...
Иначе
ВидСубк = ПланыВидовХарактеристик.ВидыСубконтоУпр.НайтиПоНаименованию(ВидСубконто.Наименование);
...
КонецЕсли;
КонецПроцедуры
68 Armando
 
10.03.13
13:25
(42) "В" это SQLный IN. Использует индексы. Инфа 146%.
69 vogenut
 
10.03.13
18:32
8.3.2 пробовал? Там говорят регистр бухгалтерии ускорили, тока реструктуризация нужна