Про оптимальность, производительность (реквизиты от ссылки через точку)

1. xaozai 12.03.24 12:51 Сейчас в теме
Известно, что при обращении к реквизиту (от ссылки) через точку, делается запрос к БД, при этом, получаются данные по всем реквизитам и табличным частям, а затем из этих данных выбирается значение, имя которого следует после точки.

Например:
Контр = Справочники.Контрагенты.НайтиПоНаименованию("Фирма 777", Истина);
ИНН = Контр.ИНН; // здесь будут получены все данные по ссылке и из полученного будет выбран ИНН
Сообщить("ИНН: " + ИНН);

Вероятно, аналогично будет с такой конструкцией:
ИНН = Контр["ИНН"];

Когда реквизитов, табличных частей в объекте не много, это не критично, но когда много, делать такие запросы - это не оптимально. Особенно, это будет заметно при обращении через точку в теле какого-то цикла.

Вопросы: зачем вообще в платформу добавлена такая не оптимальная возможность обращения к реквизитам, через точку, где её можно использовать? Есть ли какие-то простые и удобные способы получения значения одного реквизита, имея ссылку, кроме формирования текста запроса динамически?
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. Sashares 34 12.03.24 12:55 Сейчас в теме
(1)
Есть ли какие-то простые и удобные способы получения значения одного реквизита, имея ссылку, кроме формирования текста запроса динамически?


ЗначениеРеквизита = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка,ИмяРеквизита);
3. xaozai 12.03.24 13:00 Сейчас в теме
(2)
ЗначениеРеквизита = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка,ИмяРеквизита);

Там тоже делается динамическое формирование запроса + еще проверки (доп. запросы) (ИМХО, не всегда нужные). Тоже не очень оптимально.
8. Sashares 34 12.03.24 14:35 Сейчас в теме
(3)
Тоже не очень оптимально.

Смиритесь.
Либо все писать оптимально самому, либо использовать библиотечное, может не очень оптимальное, зато уже существующее.
Причем если писать самому, совсем не факт, что у вас получится оптимальное решение. Косяки могут быть везде.

Если нужен один реквизит одного объекта, то данная функция общего модуля позволит его достаточно оптимально получить. Как минимум, оптимальнее, чем через точку от ссылки.
5. Said-We 12.03.24 13:20 Сейчас в теме
(2)
ЗначениеРеквизита = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка,ИмяРеквизита);
Вызов функции/процедуры это дополнительное использование стека, исполнение кода - это работа интерпретатора + исполнения текста на языке 1С самой процедуры/функции с попытками исключения и обращения к метаданным, построение динамического текста запроса. Разбор строки с именами полей через разделитель.
Только в "ОбщегоНазначения.ЗначениеРеквизитаОбъекта" и такая же "ЗначенияРеквизитовОбъекта" кода на 250 строк + вызовы функций/процедур из других модулей. И это только для того, чтобы получить реквизит у ссылки, который и так можно получить, просто обратившись по имени через точку или через [], если точно знаешь, что этот реквизит есть :-)
Возвращает функция "ЗначенияРеквизитовОбъекта" структуру. Структура это работа с динамической памятью. И далее обращение к элементам структуры - это тоже обращение либо через точку либо по имени поля.
7. Sashares 34 12.03.24 14:30 Сейчас в теме
(5)Ужасно, ужасно.

И далее обращение к элементам структуры - это тоже обращение либо через точку либо по имени поля.


Предлагаете запретить точки?
12. Said-We 12.03.24 14:52 Сейчас в теме
(7)
Предлагаете запретить точки?
Так вопрос автора стоял, что делать, что бы не обращаться через точки. Вы как альтернативу перелагаете функцию общего модуля. А по факту предлагаемая Вами функция этим только и занимается, только внутри.
13. Sashares 34 12.03.24 14:54 Сейчас в теме
(12)Ну вы до абсурда то не доводите.
Обращение через точку - это обращение к реквизитам ссылки через точку. Что означает считывание всего объекта в память.
А не любые точки.
14. spacecraft 12.03.24 14:54 Сейчас в теме
(12)
А по факту предлагаемая Вами функция этим только и занимается, только внутри

сами смотрели?
Там по факту запрос строится для получения по ссылке нужных реквизитов.
15. Said-We 12.03.24 14:57 Сейчас в теме
(14)
Там по факту запрос строится...
А я как-то по другому это в {5} описал?
16. spacecraft 12.03.24 15:01 Сейчас в теме
(15) там набор слов без смысловой нагрузки.
приравниваете получение реквизитов по ссылке через точку и обращение через точку полученных в структуру данных реквизитов через запрос.
17. Said-We 12.03.24 15:03 Сейчас в теме
(14)
по ссылке нужных реквизитов
При обращении через точку табличные части тянутся?
18. spacecraft 12.03.24 15:05 Сейчас в теме
(17)
При обращении через точку табличные части тянутся?

уточняйте вопрос.
При обращении через точку по ссылке - тянутся.
При использовании метода БСП, если не выбрали получение ТЧ, то нет. Только то, что запросили.
19. Said-We 12.03.24 15:25 Сейчас в теме
(18)
При обращении через точку по ссылке - тянуться и данные табличных частей.
Интересно получается.
Для использования БСП в части работы с теми же адресами, необходимо в объекте предусмотреть табличную часть "КонтактнаяИнформация", вместо того, что бы хранить такую информацию в отдельной структуре.
А чтобы не тянуть адресную информацию каждый раз при обращении к объекту, из-за такой структуры данных (с табличной частью), необходимо использовать отдельную функцию.
И всё это что бы отделить БСП от прикладного решения. Ранее же контактная информация хранилась в отдельном регистре и у этого РС было измерение объект составного типа.

Т.е. каждый раз при решении проблемы создается очередная проблема, которая потом героически решается с созданием следующей. :-) Я ничего не упустил.
20. Sashares 34 12.03.24 16:06 Сейчас в теме
(19)Контактная информация это ни о чем.
Не будет там тысяч строк. И сотен строк тоже не будет.
10 строк, может 20, вряд ли больше.
21. xaozai 12.03.24 16:27 Сейчас в теме
(20) Контактная информация да, не критично.
Хуже, когда надо получить реквизит шапки какого-то документа, у которого 5 табличных частей, в которых больше 10 тыс. строк, и реквизитов табличных частей более 20.

Мне просто попалась конфа, разработанная подрядчиками (франчайзи), где в нескольких местах встречаются конструкции примерно такого вида:

Для Каждого Док Из МассивПолученныхДокументовСтруктура Цикл
    Для Каждого Рекв Из Док.Ссылка.Метаданные().Реквизиты Цикл
        Если Док[Рекв.Имя] <> Док.Ссылка[Рекв.Имя] Тогда
            Изменен = Истина;
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

У франча нет программистов не специалистов, т.е., без сертификатов.
Но это же капец, нет?

Суть в том, что по самописному обмену (через web-сервис) приходят данные разных видов документов, заносятся в структуру, структура дополняется ссылками на существующие в базе документы и перед записью документов таким образом проверяется, изменились данные или нет.

То же самое делается для табличных частей.

И еще, уже после записи сделанные изменения сохраняются в регистр, где снова отрабатывают примерно такие же циклы, чтобы определить, что именно записать в регистр.
🤦‍♂️
24. Sashares 34 12.03.24 16:47 Сейчас в теме
(21) В общем случае конечно жесть, и можно сделать лучше.
Но если организация в базе не большая, и документы маленькие - без ТЧ, или с небольшими ТЧ, и их не много, то сильно на производительности это может не сказаться.
25. xaozai 12.03.24 17:04 Сейчас в теме
(24) В здешнем случае, этот обмен - это самое критичное место во всей этой разработке.
Данных очень много, более 150 филиалов... Допускаю, конечно, что конечные разработчики, которым скинули часть задачи по ТЗ, этого не знали... И поэтому, тем, для кого важно качество своей работы, имеет смысл отучать себя писать так, в принципе...
26. Said-We 12.03.24 17:55 Сейчас в теме
(21)
и перед записью документов таким образом проверяется, изменились данные или нет
Не проще ли работать не с данными, а с версиями. И не перед записью, а до того, как решил заполнить, полученными данными. В источнике же версия есть? Версия поменялась, значит надо перезаполнить, и, если захотелось, проверить что именно поменялось и поменялось ли :-).

Ну и главный вопрос. Если объект не поменялся по существу, то чего он в обмен попал и решил по веб сервису в приемник "прилететь"?
27. Sashares 34 12.03.24 18:09 Сейчас в теме
(26)
Ну и главный вопрос. Если объект не поменялся по существу, то чего он в обмен попал и решил по веб сервису в приемник "прилететь"?


Например, при групповом перепроведении может возникать подобная ситуация.
28. xaozai 12.03.24 19:24 Сейчас в теме
(26) Некоторые данные там загружаются консолидированно.
Т.е., в источнике берутся проводки без ненужных аналитик за определенный период и загружаются в документ приёмника. Тут сомнительно, но можно понять эту проверку (если бы не в таком виде).
А вот для чего это всё распространили на другие объекты, я пока не понимаю…
30. Said-We 13.03.24 01:31 Сейчас в теме
(28)
А вот для чего это всё распространили на другие объекты, я пока не понимаю…
По моему проще принять тогда всё что пришло, чем что-то анализировать. На анализ времени уйдет вагон и тележка.
Консолидированная база и нужна для того, что-бы работать как приёмник.

Если уж прям очень хочется сравнивать и внутреннее содержание объектов, то проще рассчитать для каждого объекта какой-нибудь MD5 или подобное. При сохранении рассчитывать его и хранить его в объекте. При обмене передавать и его в том числе. Считай, что версия объекта с учетом содержания (без некоторых служебных реквизитов - например ВерсияОбъекта). Во входящих данных прилетит ссылка, MD5 в добавленном реквизите и всё содержимое объекта. А в ранее принятых данных этот MD5 уже есть. Если равны, то можно и не грузить и не бегать по всем реквизитам и по всем табличным частям, и что-то там проверять. Считайте, что была просто перезапись объекта в источнике без изменений.

Меня удивляет, что на уровне платформы этого не сделано. И при каждой записи объекта версия меняется как счетчик количества записываний.
6. booksfill 12.03.24 13:27 Сейчас в теме
(1)
Вопросы: зачем вообще в платформу добавлена такая не оптимальная возможность обращения к реквизитам, через точку, где её можно использовать


Возвращаемые значения кэшируются, поэтому, если потом получить что-то еще "через точку", то запроса к базе не будет.

Более того, при таком подходе, во всяком случае в транзакции, 1С гарантирует целостность получаемых данных - чего не будет, если несколько раз вызвать ОбщегоНазначения.ЗначениеРеквизитаОбъекта.

Получается, что есть ряд случаев, когда это оптимальней, чем таскать по одному реквизиту.
Если оно вам не надо, то есть удобные методы БСП.

Отвечаю сразу на вопрос "а мы сразу кааак выберем, у нас и метод в БСП есть, все нужное" - не всегда это просто сделать, хотя бы с точки зрения читабельности кода.

Т.е. "точка" еще дает читаемость кода, если набор нужных реквизитов заранее не определен.

А так, да, вопроc из серии " а зачем в 1С goto?"
29. user1880116 12.03.24 19:45 Сейчас в теме
(6)
в транзакции, 1С гарантирует целостность получаемых данных - чего не будет, если несколько раз вызвать ОбщегоНазначения.ЗначениеРеквизитаОбъекта
А расскажи, пожалуйста, поподробнее.
22. starik-2005 3039 12.03.24 16:27 Сейчас в теме
(1)
Вопросы:
Отлично!
зачем вообще в платформу добавлена такая не оптимальная возможность обращения к реквизитам, через точку, где её можно использовать?
Обращение к реквизитам через точку в ссылке - это плохо. То, что оно кешируется - это плохая отмазка. В общем, не стоит так делать.
А зачем это добавлено? Для начала - это "совместимость" с 7.7, т.к. там не было SQL-подобных запросов, если не считать расширений для скульных баз. Ну и это реализация ОРМ, т.е. объектно-реляционной модели, т.к. этакого объекта с полным набором связанных данных для чтения. И только со временем, когда базы данных на 1С стали расти, на \то стали обращать так много внимания. В действительности, уже давно рекомендации 1С сводятся к тому, чтобы в запросе выбирать достаточное количество параметров, чтобы обработать их в последствии. Но если речь идет о работе с единичной ссылкой, то, возможно, в этом и нет никакой проблемы. Проблема начнется тогда, когда объектов станет неопределенное количество.
Есть ли какие-то простые и удобные способы получения значения одного реквизита, имея ссылку, кроме формирования текста запроса динамически?
Если это одна ссылка, то можно и через точку. Другое дело, что это может превратиться в какой-нить цикл, а это уже запрос в цикле, что считается плохо. И вообще, все зависит от контекста задачи. Если нужны несколько реквизитов одной ссылки, то можно через точку. Если же это разные ссылки, то лучше через запрос, при том отдельно написанный для этого вот случая. Ну и если это какой-то костыль временно-постоянный, то любой метод полезен, который создаст ценность за минимальное время.
23. xaozai 12.03.24 16:34 Сейчас в теме
(22)
А зачем это добавлено? Для начала - это "совместимость" с 7.7, т.к. там не было SQL-подобных запросов, если не считать расширений для скульных баз.

Наверное, правильнее это назвать атавизмом.
Как минимум, поведение платформы в 8.х можно было изменить, сохранив такой синтаксис. ИМХО.
4. laperuz 46 12.03.24 13:18 Сейчас в теме
Там ещё кэширование есть при первом обращении через точку. Так что иногда подождать попадания в кэш объекта и потом обращения к нему будет быстрее, чем каждый раз лазить в базу
9. Said-We 12.03.24 14:45 Сейчас в теме
(8) В чем оптимальность получения с помощью функции:
ЗначениеРеквизита = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка,ИмяРеквизита);
?
10. Sashares 34 12.03.24 14:52 Сейчас в теме
(9) Это библиотечная функция, которая предназначена для возвращения значения реквизита ссылки. Реквизит получается запросом.
Ее используют все разработчики типовых. Всем нормально.
Если вас она не устраивает, сделайте свою.
Вопрос в чем, не очень понимаю?
11. nomad_irk 76 12.03.24 14:52 Сейчас в теме
(9одноразовом походе в БД за нужными данными.
31. muskul 14.03.24 02:25 Сейчас в теме
На самом деле если взять в большинстве случаев узкое место не получение реквизитов через точку, а в целом паутина и спагетти кода
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот