Динамический список. Что не так?

03.04.26

Разработка - Механизмы платформы 1С

Чего мне не хватает в динамическом списке...

Пролог

Для начала давайте вспомним, как работает динамический список. Обратим внимание именно на режим порционной выборки данных. В документации по платформе об этом очень ёмко сказано так: "Система автоматически выполняет считывание данных запроса порциями, по мере навигации пользователя по списку"

https://v8.1c.ru/platforma/dinamicheskiy-spisok/

Также на ИТС есть более подробное описание режимов порционной выборки:

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

Динамическое считывание данных выключено, задана не виртуальная основная таблица или одна из следующих таблиц: СрезПервых, СрезПоследних, ЗадачиПоИсполнителю, КритерииОтбора, ДвижениеСубконто. Используются запросы, выбирающие по 1000 записей в буфер на сервере, по мере необходимости данные передаются на клиент.  Менее эффективно, чем динамическое считывание;

https://its.1c.ru/db/v8std/content/732/hdoc

Суть, к чему я подвожу, - здесь одна:

Платформа автоматически накладывает на выборку данных в запросе динамического списка некоторые отборы, которые мы не видим, и управлять ими не можем!

 

Практика

В запросе динамического списка мы очень часто хотим обогатить выборку дополнительными данными.

Очень часто встречается соединение с выборкой текущих остатков, или среза последних цен.

Да, это не хорошо, не оптимально, и т.д. но именно такой пример приведен в документации по платформе, по первой ссылке. вот картинка оттуда :)

 

 

И это очень частая практика во многих кастомных разработках!

Да, при всём желании, на виртуальные таблицы в примере навряд ли наложатся ограничения по Товару, но на практике также бывает выборка полегче, например из табличных частей выводимых в списке документов, либо из других связанных с ними таблиц. И здесь уже можно подумать о наложении ограничений, чтобы не тянуть лишние данные.

 

Затруднения

Мы не всегда можем просто левым соединением добавить нужные поля из других таблиц.
для этого, мы сначала собираем нужные нам данные, обрабатываем, группируем  и т.д.,
кладём их во временные таблицы запроса...

И, в итоговой выборке - к основной таблице динамического списка делаем левое соединение с временной таблицей, уже содержащей нужные нам данные в нужном виде.

Пример выборки таких данных

ВЫБРАТЬ
    СправочникДоговорыКонтрагентов.Владелец КАК Владелец,
    КОЛИЧЕСТВО(СправочникДоговорыКонтрагентов.Ссылка) КАК Количество
ПОМЕСТИТЬ ТаблицаКоличествоДоговоров
ИЗ
    Справочник.ДоговорыКонтрагентов КАК СправочникДоговорыКонтрагентов
СГРУППИРОВАТЬ ПО
    СправочникДоговорыКонтрагентов.Владелец

При подготовке дополнительных данных желательно разумно ограничить выборку. Понимаем, что в последней выборке будем присоединять левым соединением к основной таблице, но ограничить выборку хочется уже сейчас, когда мы помещаем её во временную таблицу.

Поэтому мы пишем примерно следующее:

...
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК ТаблицаОтбораКонтрагентов
ПО СправочникДоговорыКонтрагентов.Владелец = ТаблицаОтбораКонтрагентов.Ссылка

В надежде на то, что таблица "Справочник.Контрагенты" - это основная таблица динамического списка,
и мы предполагаем выборку данных порциями.

 

Но это не так!

Такая схема подхватывает все установленные на основную таблицу пользовательские отборы; размер нашей выборки во временной таблице действительно уменьшается, но ...

 

Есть проблема!

Когда мы пишем выборку из основной таблицы динамического списка, и помещаем её во временную таблицу, то порционная выборка тут не действует!

При отсутствии пользовательских отборов, во временную таблицу будут выбраны все данные. И даже с нашими или пользовательскими отборами, размер выборки может оказаться неприлично большим.
Это при том, что в финальной выборке, как заявлено, будет не более 1000 строк, или даже примерно 50 в случае, когда "Динамическое считывание данных включено".

 

Моё предложение

Я уже отправил предложение вендору на @platform_suggestions; мне даже через 5 дней ответили :)

 

 

Чего мне не хватает...

Иногда нам действительно нужно выбирать из основной таблицы все данные, либо накладывать иные отборы на неё, эта логика уже давно заложена в платформе 1С.

Но, вот если бы была возможность конкретно указать, что здесь и сейчас нам нужна порционная выборка данных... ?

Полностью аналогичная выборке основной таблицы динамического списка.

Например, применительно к выборке из основной таблицы, дописать в тексте запроса что-то вроде "Выбрать Динамически":

ВЫБРАТЬ // ДИНАМИЧЕСКИ
    СправочникКонтрагенты.Ссылка КАК Ссылка
ПОМЕСТИТЬ ТаблицаОтбораКонтрагентов
ИЗ
    Справочник.Контрагенты КАК СправочникКонтрагенты  { ВЫБРАТЬ ДИНАМИЧЕСКИ }

Так, мы сможем ограничить любые наши дополнительные выборки данных только теми строками основной таблицы, которые будут фактически участвовать в запросе при формировании динамического списка.

При этом, существующая логика работы платформы никак не испортится.

 

Полный текст примера:

 

 

Есть и обратная сторона этой проблемы.

Однажды у меня никак не получалось выбрать из основной таблицы динамического списка все данные и поместить их во временную таблицу.

Всегда автоматически накладывались пользовательские отборы.

Пример такой надобности:

Когда данные справочника наполняются из разных мест, например, разных сервисов, классификаторов, и т.д. Они частично дублируются по некоторому критерию, например по ИНН, но получены из разных источников.

В этом случае хочется вывести в динамическом списке флаг наличия этого же элемента среди других источников, но сделать это не получится, если вдруг пользователь поставит отбор на текущий источник.

Вот если бы была возможность указать, что здесь нужна полная выборка...

ВЫБРАТЬ // ВСЕ
    СправочникКонтрагенты.Ссылка КАК Ссылка
ПОМЕСТИТЬ ТаблицаОтбораКонтрагентов
ИЗ
    Справочник.Контрагенты КАК СправочникКонтрагенты  { ВЫБРАТЬ ВСЕ }

 

Эпилог

Думаю, что это не только моя боль...

Считаю, что технически организовать этот функционал в платформе - задача относительно не сложная, но при этом очень полезная.

Надеюсь, что разработчики платформы меня услышат, и однажды мы сможем писать запросы в динамическом списке более оптимально

Прошу считать эту статью моим "открытым письмом" к Вендору 1С :)

Вступайте в нашу телеграмм-группу Инфостарт

Динамический список

См. также

Механизмы платформы 1С Программист Бесплатно (free)

Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?

16.07.2025    30897    TitanLuchs    106    

149

Механизмы платформы 1С Работа с интерфейсом Программист Стажер 1С:Предприятие 8 Бесплатно (free)

Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).

03.02.2025    16919    bayselonarrend    127    

68

Механизмы платформы 1С Программист 1С:Предприятие 8 Бесплатно (free)

В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.

30.01.2025    20375    user2122906    9    

66

Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Программист 1С:Предприятие 8 Бесплатно (free)

Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.

17.01.2025    35291    user2122906    12    

62

Механизмы платформы 1С WEB-интеграция Программист 1С:Предприятие 8 Бесплатно (free)

В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.

14.01.2025    31488    dsdred    106    

148

Механизмы платформы 1С Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    27739    bayselonarrend    22    

176

Механизмы платформы 1С Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    15068    dsdred    22    

86
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Трактор 1279 03.04.26 09:38 Сейчас в теме
Плюс за:
1. Писал сам. Не используя ИИ.
2. Интересное предложение.

Замечание.
Временные таблицы в динамических списках использовать не рекомендуется. Очень сильно не рекомендуется.

Не проверял можно ли подключить к динамическому списку менеджер временных таблиц чтобы всё-таки их использовать, заполненные до показа динамического списка. Хорошо бы проверить, но лень.
2. pbelsib 6 03.04.26 09:49 Сейчас в теме
Спасибо! в этом моя идентичность :)
хотя - заставку ИИ нарисовал, и очень тонко подметил проблематику дин.списка.

чтобы узнать кол-во данных во временной таблице динамического списка,
я делаю так:
считаю Количество(*), помещаю во временную таблицу,
и также присоединяю к основной выборке; вывожу в колонку.

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

Важно! может завершиться аварийно. особенно на несвежих версиях, вроде до 25. непомню
3. pbelsib 6 03.04.26 09:55 Сейчас в теме
про "не рекомендуется" - только ленивый не сказал.
я очень много всякого легаси-кода видел, перелопачивал...
там реально этого много.

имхо, - если знаешь что делаешь, и получается. то можно.
может мы табличку всего из 100 элементов максимум присоединяем...

а вот через ПриПолученииДанныхНаСервере - там столько ньюансов...
проблемы передачи параметров с/на клиента,
неполноценность вновь добавленных полей (отсутствие отбора по ним и сортировки),
ну и главное - всё же дополнительный запрос, и он- в цикле.
это потому, что сам дин.список может выбрать 1000 строк, а событие при каждом чихе вызывается.

P.S. у меня не тысяча, а 10 тысяч по факту выбиралось, когда исследовал.
4. Sashares 33 03.04.26 10:05 Сейчас в теме
(3)
а вот через ПриПолученииДанныхНаСервере - там столько ньюансов...
проблемы передачи параметров с/на клиента,
неполноценность вновь добавленных полей (отсутствие отбора по ним и сортировки),


Все проблемы решаемы.
А сортировка по рандомным полям ДС это одна из причин медленной работы ДС.
EvgeTrofi; +1 Ответить
5. pbelsib 6 03.04.26 10:16 Сейчас в теме
(4)
Все проблемы решаемы.

если знаете как делать не более 1 дополнительного запроса на один исходный запрос,
поделитесь пожалуйста. буду рад новым идеям.

Сортировка по ссылочным полям - совершенно другая тема...
мне кажется, разработчики и сами знают, что впринципе решить можно,
но там нужен совершенно другой подход к построению выборки запроса.
6. Sashares 33 03.04.26 10:26 Сейчас в теме
(5)
если знаете как делать не более 1 дополнительного запроса на один исходный запрос,
поделитесь пожалуйста. буду рад новым идеям.

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

Если запихать весь текст запроса в запрос ДС он выполнится условно 1 раз, но кому от этого будет лучше, если он висит по минуте?

Сортировка по ссылочным полям - совершенно другая тема...

Тут даже не про ссылочные поля речь.
Речь про любые поля списка, которые не рассчитаны на сортировку по ним.

Особенности использования варианта индексирования "Индексировать с доп. упорядочиванием"

При описании в метаданных реквизитов различных объектов существует возможность установить свойство Индексировать. Это свойство позволяет разработчику конфигурации указать системе необходимость построения в базе данных отдельного индекса по соответствующему реквизиту.

Кроме варианта "Индексировать" в данном свойстве для большинства объектов можно установить вариант "Индексировать с доп. упорядочиванием". Данный вариант предназначен, прежде всего, для использования в динамических списках.

В варианте "Индексировать" строится индекс непосредственно по реквизиту. Индекс также дополняется ссылкой, чтобы обеспечить определенный порядок записей в индексе при повторяющихся значениях реквизита.

В варианте "Индексировать с доп. упорядочиванием" индекс строится по реквизиту, а также по некоторому полю, которое обычно используется для упорядочивания объектов этого типа. Для справочника индекс в зависимости от основного представления дополняется кодом или наименованием. А для документа, индекс дополняется датой. Этот индекс также дополняется ссылкой.

В варианте "Индексировать" в динамическом списке может быть обеспечен эффективный просмотр больших объемов информации с упорядочиванием по данному реквизиту, так как для этого будет использоваться созданный индекс.

В варианте "Индексировать с доп. упорядочиванием" в динамическом списке может быть обеспечен эффективный просмотр больших объемов информации с отбором по значению данного реквизита и с упорядочиванием, соответствующим основному упорядочиванию для данного объекта. В этом случае наличие индекса включающего реквизит, по которому выполняется отбор, и поля основного упорядочивания позволит системе использовать индекс при просмотре списка.

Разумеется, индексы так же влияют и на другие способы выборки информации (получение данных с помощью методов менеджеров объектов или запросов).

Таким образом при определении варианта свойства Индексировать следует исходить из того, какие варианты выборки информации необходимо оптимизировать в первую очередь. Например, если требуется просмотр списка с отбором по реквизиту, то имеем смысл использовать вариант "Индексировать с доп. упорядочиванием". А если индекс нужен, например, только для поиска с помощью запроса объектов по данному реквизиту без упорядочивания, то лучше использовать вариант "Индексировать", чтобы создаваемые индекс требовал меньше ресурсов системы.

Подробно состав индексов формируемых системой при различных сочетаниях свойств метаданных приводится в с статье "Индексы таблиц базы данных".
Показать

Отсюда https://its.1c.ru/db/metod8dev/content/2742/hdoc
7. pbelsib 6 03.04.26 10:33 Сейчас в теме
(6) я кстати именно эту идею в статье и описал:
"ограничить выборку малой порцией данных", только уже на стадии формирования самого основного запроса.

уверен, тут выигрышь подхода с временными таблицами будет неоспорим,
по сравнению с подходом на событии.

так как уже сейчас, на практике сравнивая различные кейсы,
при построении на событии и на врменных таблицах,
я вижу, что часто выигрыгш на стороне временных таблиц.
8. Sashares 33 03.04.26 10:40 Сейчас в теме
(7)
так как уже сейчас, на практике сравнивая различные кейсы,
при построении на событии и на врменных таблицах,
я вижу, что часто выигрыгш на стороне временных таблиц.


На уровне погрешности, так понимаю?

Ну и так понимаю, речь для сценария, когда данных мало.
Когда данных станет больше, все может измениться.
Но при этом "при построении на событии" результат будет сопоставимый и при большом объеме данных в ДС.

У меня есть база, где в ДС по таблице документа 1.5млн записей (если убрать отборы), и в ПриПолученииДанныхНаСервере заполняются колонки.
Особых проблем в этом нет.
9. Sashares 33 03.04.26 11:04 Сейчас в теме
(5)
если знаете как делать не более 1 дополнительного запроса на один исходный запрос,
поделитесь пожалуйста.


На каждую порцию один запрос в ПриПолученииДанныхНаСервере - сначала берем ссылки от порции данных, которая к нам пришла, а потом за один запрос получаем все доп. данные.
Но это я думаю очевидно. Но вдруг)
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
	Если Строки.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	МассивДокументов = Новый Массив;
	СоответствиеДанных = Новый Соответствие;
	Для Каждого КлючИЗначение Из Строки Цикл
		МассивДокументов .Добавить(КлючИЗначение.Ключ);
		СоответствиеДанных.Вставить(КлючИЗначение.Ключ,Ложь);
	КонецЦикла;
....

        Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		СоответствиеДанных.Вставить(Выборка.ДокСсылка, Выборка.НужноеЗначение);
	КонецЦикла;
	
	Для Каждого КлючИЗначение Из Строки Цикл
		ТекДанные = КлючИЗначение.Значение.Данные;
		Если ТекДанные.Свойство("МояКолонка") Тогда
			ТекДанные.МояКолонка= СоответствиеДанных[КлючИЗначение.Ключ];
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
Показать
10. pbelsib 6 03.04.26 11:17 Сейчас в теме
(9) для понимания:
это классический подход с событием,
а другого варианта то и нет.

но работает немножко не так...

Динамический список делает 1 запрос, и выбирает 1 тысячу строк ( без галки),
либо 30-50 строк с галкой. кстати, на быстрых каналах выгоднее выборка без галки!

далее, пользователь нажал стрелочку вверх/вниз,
и бежит по списку...
Динамический список - более не делает ни одного запроса!
а вот событие - истерично, на каждую строчку делает серверный вызов,
выполняется ваш дополнительный запрос.

по сути - запрос в цикле, ну и серверный вызов в цикле.
и разница вовсе не "на уровне погрешности"!

очень замедляет навигацию по списку, даже если в событии ничего такого не делаем.
11. Sashares 33 03.04.26 11:29 Сейчас в теме
(10)
Динамический список - более не делает ни одного запроса!


Достаточно сомнительное утверждение. С чего вдруг такой вывод?

а вот событие - истерично, на каждую строчку делает серверный вызов,
выполняется ваш дополнительный запрос.


Сейчас проверил, у меня такого поведения нет. Проверял на 8.3.24.1758.
Событие вызывается, когда я долистал до конца порции данных.
То есть я долистал до конца выведенных данных, потом выполнился запрос ДС и подгрузилась новая порция данных по всем отборам и с учетом всех сортировок, а потом выполнилось событие на эту подгруженную порцию данных.
12. pbelsib 6 03.04.26 11:53 Сейчас в теме
(11)
Дин.список выбирает порцию 1000 строк.
специально для того, чтобы не обращаться к данным лишний раз, пока вы бегаете в пределах этих 1000 строк.
как вышли за диапазон, - он сделает второй запрос, чтобы выбрать следующие 1000 строк.
убедиться в этом можно через SQL Prifiler или Тех.Журнал.

Событие - там Строки - те, что выводятся на экран.
кстати, я сейчас попробовал на 27 платформе. она меня порадовала,
это действительно не так истерично, как я видел раньше.
кол-во строк в событие получается чуть больше, чем на экране. это хорошо.
и в справке исчезла формулировка про "видимые на экране строки"

попробуйте вот так сделать

&AtServerNoContext
Procedure ListOnGetDataAtServer(ItemName, Settings, Rows)
Message(Rows.Count());
EndProcedure

у меня получается пачка по 22 -26 строк, это когда я сам список на экране зажал до 4 видимых строк, и бегаю по нему.

но опять же, это не один к одному, сравнивая с 1000 строк дин.списка.
13. Sashares 33 03.04.26 12:01 Сейчас в теме
(12)
у меня получается пачка по 22 -26 строк, это когда я сам список на экране зажал до 4 видимых строк, и бегаю по нему.


Да, первый раз 42, потом по 22, при этом список развернут на весь экран.
Проверил для разных настроек ДС - когда есть основная таблица, когда ее нет, когда включено динамическое считывание, когда выключено.
У меня работает одинаково. Запрос без временных таблиц.
То есть событие срабатывает только когда ДС получает следующую порцию данных, как и написал ранее.
Прикрепленные файлы:
14. Serg O. 318 03.04.26 13:52 Сейчас в теме
ещё ведь и RLS накладывает свои ограничения по Контрагентам / Договорам / Организациям
так что реальный запрос может быть ещё монструознее
+ отборы пользователей и добавленные ими поля (через 1, 2 а то и 3 точки)

в общем сталкивался с таким.
Динамический список тормозил неимоверно...
особенно из-за этих порций

Так, например, когда пользователь колёсиком мышки крутит... или стрелками бегает вверх-вниз
раз ... и зависло на 2 - 5 а то и 10 сек.

и выход был - просто заменой Динамического списка на ТаблицуЗначений на форме
а все запросы - под жёстким контролем (программиста)
которые в модуле обрабатываются.
а у пользователя - только строго-фиксированные отборы - поля на форме.
сразу стало шустро "бегать" при прокрутке.

(можно и СКД прикрутить если надо даже для вывода в Таблицу Значений)
так же можно и "порцию" прикрутить - экран-два это 40-100 записей
только тут нужно поле для сортировки - сама ссылка или Дата Документа например.)
15. pbelsib 6 03.04.26 13:58 Сейчас в теме
(14)
какие отборы будут в итоге наложены на основную таблицу - всегда известно разработчикам платформы,
не важно, RLS там или ещё чего-то.

наложить ровно такие же отборы на выборку из основной таблицы, помещаемую во внутреннюю таблицу - в чём проблема?

а тормозят "эти порции" как раз из за слишком громоздких соединений к ним, где порции уже не получаются.
16. Трактор 1279 04.04.26 22:01 Сейчас в теме
Что ж. Разработчики из самой 1С сегодня подтвердили, что Инфостарт не читают.
Но ничего! Поздравляю с тем, что донёс своё предложение лично.
Для отправки сообщения требуется регистрация/авторизация