Имя: Пароль:
1C
1С v8
Можно ли оптимизировать такой код запроса
0 espanol
 
23.12.13
17:14
Соединяются две таблицы с разных пакетов, по средствам левого соединения, условие соединения:
СотрудникиИВендоры.Вендор = Итоговый.Номенклатура
    ИЛИ СотрудникиИВендоры.Вендор = Итоговый.Номенклатура.Родитель
    ИЛИ СотрудникиИВендоры.Вендор = Итоговый.Номенклатура.Родитель.Родитель
    ИЛИ СотрудникиИВендоры.Вендор = Итоговый.Номенклатура.Родитель.Родитель.Родитель
    ИЛИ СотрудникиИВендоры.Вендор = Итоговый.Номенклатура.Родитель.Родитель.Родитель.Родитель

Т.к. если в запросе получаем поля, то нельзя использовать В ИЕРАРХИИ, вот приходится так делать... но из-за обращения через "." и из-за множества "ИЛИ" как я понимаю и запрос так медленно отрабатывается, там примерно по тысяч 10 записей и 10 тысячами соединяются. Минут 15 занимает примерно.
Как можно сделать, так чтобы отрабатывало быстрее?
1 Avganec
 
23.12.13
17:16
(0) расстрел за такие вещи надо делать на месте. а так, такие запросы НАДО переделывать. правда не всегда сразу видно как, но надо!
2 sapphire
 
23.12.13
17:17
(1) Там какой-то недума структуру такую учудил.
3 Fragster
 
гуру
23.12.13
17:19
РС с иерархией и обновлением и соединение по нему.
4 Fragster
 
гуру
23.12.13
17:19
ну и (1)
5 Avganec
 
23.12.13
17:19
(2) я встречал такие перлы на предыдущем месте работы, причем в больших количествах. а еще удивлялись, почему это все так медленно работает...
6 espanol
 
23.12.13
17:20
(3) ничего не понятно, напиши подробнее
7 Avganec
 
23.12.13
17:21
либо (3), либо пробовать сделать отдельно, в отдельном запросе, либо... вариантом много
8 sapphire
 
23.12.13
17:21
(3) А что даст такой РС?
9 sapphire
 
23.12.13
17:22
Вообще речь о том, что писари-адинеснеги вообще не думают, когда ваяют структуру метаданных.
Это же кому-то в голову пришло же подсунуть группу товара в какой-то справочник в виде поля "Вендор". Идиотизм.
10 Avganec
 
23.12.13
17:24
(9) это не недумают, это просто не знают. либо мало опыта, либо действительно нет серого вещества
11 MadHead
 
23.12.13
17:25
(0) про то что это все плохо повторятся не хочу. Но думаю если поля с родителями выбрать в таблицу Итоговый и проиндексирвоать по этим полям будет быстрее.
12 MadHead
 
23.12.13
17:26
(0) СотрудникиИВендоры тоже добавить индексы по полям которые участвуют в условии соединения (если их нету)
13 H A D G E H O G s
 
23.12.13
17:28
(11)(12) Это ничего не изменит.
14 MadHead
 
23.12.13
17:30
(13) Почему же не изменит? Если соединение пойдет по индексированным полям, то очень даже изменит. Пусть автор попробует и напишет сюда результат
15 YAGolova
 
23.12.13
17:30
(9) А что в этом такого сверхполохого. У меня такое сплошь и рядом. И даже если честно более красивого решения придумать не могу. К примеру надо запретить определенному клиенту отгрузку товаров из определенной группы - как нормально организовать структуру. Очень итересно, честное слово буду пользоваться
16 H A D G E H O G s
 
23.12.13
17:31
НоменклатурныеГруппы помогут вам.
17 H A D G E H O G s
 
23.12.13
17:31
(14) Потому что главная проблема
Итоговый.Номенклатура.Родитель.Родитель.Родитель.Родитель
18 sapphire
 
23.12.13
17:34
(14) От "В ИЕРЕАХИИ" не избавишься.
ИМХО, надо получить все возможные пары
Номенклатура-Вендор
19 MadHead
 
23.12.13
17:34
(17) главная проблема по этому всему провести соединение.
20 selenat
 
23.12.13
17:36
(19) ИЛИ в условии левого соединения - зло. А через тот же самый прием объединения и группиовки делается элементарно. А вот как лучше со всеми этими родителями поступить - эт подумать надо...
21 MadHead
 
23.12.13
17:36
(15) я подобную задачу оптимизировал следующим образом. При установке флага "запрета выборка" родителю, сразу флаг проставляется всем подчиненным. И возможность запрета можно определить по ближайшему родителю
22 H A D G E H O G s
 
23.12.13
17:38
(19) Нет.
Главная проблему 1С провести соединение
Итоговый.Номенклатура.Родитель.Родитель.Родитель.Родитель
100500 раз
23 selenat
 
23.12.13
17:39
Таки 4 временные таблицы с последовательным выделением в них родителей, а потом объединение запросов со всеми этими таблицами. И будет счастье.
24 YAGolova
 
23.12.13
17:40
(21) А при появлении очередного ближайшего родителя внутри головного родителя так же отслеживать и делать соответствующую запись? А где гарантия того, что пользователь набил эти флаги не на конкретные группы внутри группы и на появление новой группы этот флаг распространяться не должен?
25 MadHead
 
23.12.13
17:40
(18) я не спорю что мой вариант все равно остается кривым решением и не предусматривает (как и вариант автора) произвольной вложенности групп. но если в таблицу Итоговый добавить 4 поля с родителями разного уровня и по ним установить условие соединение будет на много лучше.

(22) вот по этому мы в таблице Итоговый получим 4 индексированных реквизита родитель1, родитель2, родитель3, родитель4
26 H A D G E H O G s
 
23.12.13
17:41
Пакетный запрос с менеджером ВТ
Получаем все различные вендоры - номенклатуры

"Рекурсивно" строим в цикле (только сцуко правильно) - все различные родители по списку номенклатуры.

Получаем таблицу значений
Номенклатура Родители

Засовываем в запрос.

Делаем все на сервере 1С.

Профит.
27 MadHead
 
23.12.13
17:42
(24) это уже от логики зависит, если пользователь набил на конкретные группы то нужный флаг без всяких доп действий можно получить у ближайшего родителя
28 selenat
 
23.12.13
17:45
Даже с произвольной вложенностью иерархии сделать можно самым оптимальным способом.
29 selenat
 
23.12.13
17:51
Это как раз прекрасный пример запроса, где идеально работает техника замены левого соединения объединением и группировкой.
30 bolobol
 
23.12.13
17:53
(29) Вопрос стоит: "Как сделать?", а не какую технику использовать. Если объединяемую таблицу соберать более чем через одну точку - тот же результат будет.
31 H A D G E H O G s
 
23.12.13
17:54
(29) Не работает.
(30) Результат будет лучше, но все равно мрак.
32 selenat
 
23.12.13
17:57
(31.1) отлично работает. Причем не просто отлично, а оптимально.
33 selenat
 
23.12.13
17:57
Не успею сейчас описать. Через минуту убегаю.
34 bolobol
 
23.12.13
17:57
(31) Понятно, что лучше - индексирование на вложенность через точку не работает, а значит в (0) уже теряем индексы, а в объединённой таблице уже и назначить индексы можно, если сами не подцепятся.
35 bolobol
 
23.12.13
18:00
Чёт вот не могу сообразить, как же собрать объединённую таблицу, неужели ж по максимальному уровню справочника Номенклатура переделывать количество временных таблиц???
36 MadHead
 
23.12.13
18:01
(35) а как еще? )))
37 H A D G E H O G s
 
23.12.13
18:01
(35) Думаю, да. Только не временных таблиц, а объединяемых запросов.
38 H A D G E H O G s
 
23.12.13
18:01
(36) Кодом собрать Номенклатура - Родители.
Это оптимум.
39 Fragster
 
гуру
23.12.13
18:02
в группу и элемент иерархического справочника (или в отдельный регистр сведений) добавить реквизиты для групп: левое значение и правое значение, для элементов просто "значение", хранить там значения:

для иерархии (только группы, элементы только на нижнем уровне, в реальности немножко посложнее)

а
-б1
--б1в1
--б1в2
-б2
--б2в1

а: 1 и 15
б1: 2 и 9
б1в1: 3 и 5, у подчиненных элементов - 4
б1в2: 6 и 8, у подчиненных элементов - 7
б2: 10 и 14
б2в1: 11 и 13, у подчиненных элементов - 12
40 Fragster
 
гуру
23.12.13
18:02
в иерархии тогда превращается в "реквизит между левоезначение и правоезначение"
41 H A D G E H O G s
 
23.12.13
18:05
(39) http://lurkmore.to/%df_%ed%e8%f5%f3%ff_%ed%e5_%ef%ee%ed%ff%eb

Бедные твои пользователи.
42 Fragster
 
гуру
23.12.13
18:08
43 H A D G E H O G s
 
23.12.13
18:09
(42) И что это даст?
44 Fragster
 
гуру
23.12.13
18:10
(42)+ немного оптимизированный из-за различия групп и элементов
45 Fragster
 
гуру
23.12.13
18:10
(43)->(40)
46 bolobol
 
23.12.13
18:10
(42) Это регулярная перестройка дерева. Причём - всего, целиком от места изменения до упора.
А построить его - всё равно, что перебрать все элементы, даже дороже.
47 Fragster
 
гуру
23.12.13
18:10
минус - это при изменении вложенности групп надо много обновлять
48 Fragster
 
гуру
23.12.13
18:11
(46) как часто вы меняете именно структуру папок (при переносе элементов только одно значение меняется)
49 Fragster
 
гуру
23.12.13
18:12
да и вообще каково соотношение операций чтения/записи для справочника
50 bolobol
 
23.12.13
18:14
(48) Я - не менял ни разу, а вот пользователи... Да просто так иногда, пересунут чего-то куда-то.
Но если так индексировать с пробелами на вставку, а так же уровень подключить, то при перемещении только перемещаемую ветку переиндексировать, так сказать. Вроде и жизнеспособно, даже. Хм, Респект!
51 Fragster
 
гуру
23.12.13
18:16
(50) были бы у 1с запросы на апдейты - то вынимание из структуры - 1 запрос, вставка в структуру - второй запрос и все. если немного подумать - то вообще одним запросом можно переносить
52 Fragster
 
гуру
23.12.13
18:19
еще есть Materialized Path, но он мне меньше нравится почему-то (ПолныйКод в терминах 1с)
53 ILM
 
гуру
23.12.13
18:25
Ответ уже дан в (26)
54 RomanFire
 
23.12.13
19:11
полностью ответ не дан
55 sapphire
 
23.12.13
19:14
Чего не хватает в (26)?
56 Лефмихалыч
 
23.12.13
19:20
(43) это даст between, сравнивающий целые числа вместо В ИЕРАРХИИ.
Лютая головоломка, но работает.
57 Fragster
 
гуру
23.12.13
19:26
(56) на самом деле я не вполне понимаю, почему в платформу подобное не было встроено
58 Лефмихалыч
 
23.12.13
19:35
(57) платформоделы про это не в курсе. Тупо.
59 Лефмихалыч
 
23.12.13
19:37
ну или там на марше были соображения, что трудозатрахи СУБД на апдэйт границ при добавлении элементов внутрь иерархии будут больше, чем на запросы в цикле

там у них своя атмосфера какая-то
60 selenat
 
23.12.13
19:44
Значит так. У меня дома пофигуратор не стоИт, поэтому рассказываю словами.
61 Лефмихалыч
 
23.12.13
19:49
(60) всё?..
62 Fragster
 
гуру
23.12.13
19:51
(61) а тебе мало?
63 selenat
 
23.12.13
19:54
Запрос не обязательно выполнять сразу весь, а можно выполнять кусочками, накапливая в менеджере временных таблиц все новые таблицы. А заодно выполняя отдельный кусочек проверять его результат. Что это дает? Вот есть у нас временная таблица номенклатуры. Строим таблицу ее родителей. Во первых кладем ее тоже во временную, во вторых можем тут же взять ее выборку и посмотреть, не пустая ли она. Если выборка не пустая, то можем построить таблицу родителей следующего уровня и проделать те же действия. И так до тех пор, пока не получим таблицу самых верхних родителей. Это легко можно сделать в цикле и получить во временных таблицах и саму номенклатуру, и родителей всех уровней. Дальше мы во вложенном запросе делаем объединение исходной таблицы с таблицей номенклатуры и со всеми таблицами родителей. Вводя служебные поля, группируя результат этого вложенного запроса и фильтруя результат группировки получаем ответ. Причем скорость метода будет практически такая же, как если бы родители не использовались. Просто если бы мы использовали только номенклатуру, без родителей, то было бы у нас в присоединяемой таблицы скажем 100 элементов. А с учетом родителей ну будет там скажем 150 элементов. Это как раз прелесть этого метода, когда мы заменяем левое соединение объединением и группировкой. Кто-нибудь что-нибудь понял из этого потока сознания? :)
64 Лефмихалыч
 
23.12.13
19:54
(62) ну, мне пока не понятно, в чем замес и я не могу понять - заинтригован я или нет
65 Лефмихалыч
 
23.12.13
19:56
(63) а если номенклатуры полтора миллиона записей?
66 selenat
 
23.12.13
19:59
(65) пофиг. Оптимальней не будет. Будет потрачено только то время, которое действительно необходимо. А вот левым запросом с да еще с конструкцией ИЛИ в соединении рискуешь получить повесившуюся систему.
67 Лефмихалыч
 
23.12.13
20:01
(66) сорри, я ни фуя не понял, но nested-set мне нравится больше :)
68 ILM
 
гуру
23.12.13
20:02
(63) Да ну нафиг, нужно сразу связку делать пар: ном и род_ном, сначала уровень 0, потом 1 и т.д.,  а далее как с деревьями.
69 selenat
 
23.12.13
20:04
Ладно. "Мое дело прокукарекать, а там хоть не рассветай" (С)
70 selenat
 
23.12.13
20:20
(68) ни с одним деревом работа не будет делаться быстрее, чем с линейным списком того же размера. В предлагаемом мной методе номенклатура со всеми родителями по сути выстраивается в линейный список.
71 ILM
 
гуру
23.12.13
20:31
(70) Прочитайте как деревья отражаются в таблицах, а особенно про индексы для деревьев.
72 selenat
 
23.12.13
20:41
(71) я пожалуй не поленился бы реализовать свой способ для этой задачи, чтобы сравнить его по скорости с тем, что предлагаете вы. :)
73 Адимр
 
23.12.13
20:48
(63) Я до конца не врубился.

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

В итоге что получам одну таблицу или две в каком виде?
74 Адимр
 
23.12.13
20:49
или типа временные таблицы табНоменклатура, ТабРодители1, ТабРодители2 итп
75 ILM
 
гуру
23.12.13
20:53
Ну прочтите (26) и для полей Номенклатура, Родитель, Уровень создайте пакет.
76 selenat
 
23.12.13
20:53
(74) Да. И после этого как бы соединяем с объединением этих таблиц.
77 Адимр
 
23.12.13
21:05
(76) Какой вид итоговой таблицы предполагается? Две колонки? Как в (75) > (26)
78 selenat
 
24.12.13
06:40
(77) в условии задачи указано только условие для левого соединения. Для реализации этого условия в таблицах родителей сама номенклатура не нужна вообще.
79 ViSo76
 
24.12.13
08:13
Да оптимизация возможна с использованием временных таблиц. Работать будет быстро. Я такую конструкцию использую для быстрого поиска. Код набросаю чуть позже.
80 ViSo76
 
24.12.13
08:17
(63) Я практически такой метод использую. Так как количество иерархий конечное, у топикастра 4 временных таблицы которые затем объединяются
81 espanol
 
24.12.13
08:18
(11) в раз 10 стало работать быстрее, но с виду как-то ужасно выглядит =)

(37) надо будет через объедения попробовать...
82 mzelensky
 
24.12.13
08:18
(0) Я полистал ветку, но так и не понял - зачем это все? Что хотят получить в конечном итоге?
83 ViSo76
 
24.12.13
08:25
И что в этом случае разве нельзя сделать так?

ПО Итоговый.Номенклатура В ИЕРАРХИИ( СотрудникиИВендоры.Вендор )
84 ИС-2
 
naïve
24.12.13
08:27
(0) Собрать всех Родителей во временной таблице т.е Родитель.Родитель как Родитель2. Если связь только по 1 полю, то вместо или использовать условие в.  

(0) была у меня подобная тема. Тоже ругаюсь от такой структуры хранения, но ЭТО УДОБНО ПОЛЬЗОВАТЕЛЯМ. Во и приходится извращаться
85 Лефмихалыч
 
24.12.13
08:31
(82) соединить по иерархии хотят
(83) ну попробуй
86 Klesk666
 
24.12.13
08:50
Как вариант - создать реквизит и обновлять регламентным заданием
вот у меня тоже есть например в номенклатуре реквизит url
который содержит путь который надо в браузере открывать под конкретную позицию, может быть прописана в родителе+артикул, может быть прописана в самом элементе, в запросах мне это не нужно, но можно сделать регламентное задание которое прописывает для элемента номенклатура конкретное значение, и использовать быстро в запросах.
87 espanol
 
24.12.13
09:00
Через объединить, не катит, т.к. левое соединение, вот через внутреннее бы покатило, или если бы "ИЛИ" стояло в "ГДЕ", а не в условие соединения...
88 selenat
 
24.12.13
09:12
(87) "ничего то ты мишка не знаешь..." (с)
89 selenat
 
24.12.13
09:13
по ходу статью надо бы написать, дабы ссылку потом легко кидать было и не приходилось бы искать один-два важных поста по веткам обсуждения.
90 selenat
 
24.12.13
09:19
(87) смотри здесь посты 30 и 44
v8: Индексы в запросах.
91 ifso
 
24.12.13
09:58
(2) +100500
Какая структура, такой и запрос.
92 k1us181b
 
24.12.13
10:29
(91) вас смущает древовидная структура справочника?
93 espanol
 
24.12.13
10:32
(90) чето все равно какая-то офигня выходит ))
94 selenat
 
24.12.13
10:33
(93) "старайтесь лучше" (с)
95 ifso
 
24.12.13
10:44
(92) не сама структура, но ее использование
96 Reaper_1c
 
24.12.13
10:46
(92) Да за нее убивать надо.
97 mistеr
 
24.12.13
11:11
Да, транзитивное замыкание операция редкая, но иногда без нее никак. Могли бы встроить в платформу. Пусть не в запрос, но хотя бы как метод ДЗ.

Ко там постоянно тусуется на партнерских, озвучьте им при случае.
98 MadHead
 
24.12.13
11:23
(81) я предложил быстрый в реализации способ ускорения. Если сделать "мега оптимальным способом" получите еще 10% ускорения. Я бы не замарачивался и рассмотрел возможность изменить архитектуру так что бы данный флаг можно было получать по ближайшему родителю или по родителю на определенном уровне. Или создал справочник "вендоры"
99 Бледно Золотистый
 
24.12.13
11:32
(97) Тут есть кстати статья неплохая по реализации транзитивного замыкания. Может понадобится кому.
http://infostart.ru/public/158512/
100 badboychik
 
24.12.13
11:53
а что мешает в коде найти всех родителей и поместить в массив, а потом его передать в запрос ?
101 badboychik
 
24.12.13
11:55
и написать

СотрудникиИВендоры.Вендор В (&НоменклатураИРодители)
102 badboychik
 
24.12.13
11:58
Если "Итоговый.Номенклатура" это целый список, то да, selenat правильно говорит, что надо в цикле дописывать объединением родителей, а потом эту таблицу передавать дальше для соединения
103 selenat
 
24.12.13
12:02
(102) и мало того, все-таки довольно часто левое соединение само по себе строится 1Ской неоптимально. Посему я все-таки советую добиваться того же резудьтата, что дает левое соединение,  при помощи объединения и группировки.
104 MadHead
 
24.12.13
12:07
(103) на счет левого соединения 1с строит не оптимально - это очень странно. Там же запрос практически 1 в 1 на СУБД уходит. тут вероятнее всего будет прирост от замена соединения объединением, но он будет не такой уж и высокий. Субъективно около 10%
105 selenat
 
24.12.13
12:16
(104) это у вас субъективно. Я не так хорошо знаю теорию, чтобы однозначно рассказать от каких именно факторов это зависит, но за годы применения этого приема могу из своих наблюдений сделать вывод, что в ряде случаев (не всегда конечно) на больших выборках время выполнения уменьшается на порядки. А был у меня случай, когда левое соединение вообще вешало систему, так что я через пару часов ожидания снимал сеанс 1С, а запрос с объединением и группировкой отрабатывал прекрасно за несколько минут.
106 mistеr
 
24.12.13
20:18
(99) О, спасибо. Есть где применить. Тоже думал, что кодом быстрее.
Основная теорема систематики: Новые системы плодят новые проблемы.