Здравствуйте! Давайте вместе разберем одну из самых неприятных проблем в разработке 1С — это критически медленное открытие документов, особенно когда речь идет о работе с динамическими списками, оперирующими огромными объемами данных. Представим себе ситуацию, когда простой документ открывается целых 20 минут, что делает работу с ним практически невозможной.
Наш читатель столкнулся именно с такой проблемой: среднее время открытия документа составляет 20 минут. Данные табличной части документа хранятся в регистре сведений, который содержит порядка 4 миллионов записей на один документ, а общий объем регистра достигает 777 миллионов записей. Для отображения данных на форме используется ДинамическийСписок, создаваемый программно.
Автор отмечает, что время открытия документа не зависит от того, новый ли он или уже существующий. Возникает ощущение, что динамический список сначала подтягивает все записи из регистра, и только после этого к ним применяется отбор. Это предположение является ключевым, так как противоречит базовому принципу работы динамических списков, которые должны считывать данные порциями. Давайте рассмотрим эту проблему подробнее и выясним возможные причины и пути решения.
Динамические списки (ДС) в 1С — это мощный инструмент для работы с большими объемами данных. Их основная идея заключается в том, что данные считываются не сразу все, а небольшими порциями, по мере необходимости (например, при прокрутке списка). Это называется динамическим считыванием данных, и по умолчанию эта функция включена. Обычно данные считываются небольшими порциями, например, по 45 или 1000 записей, в зависимости от настроек и версии платформы.
Однако, как показывает практика, даже при включенном динамическом считывании могут возникать ситуации, когда система ведет себя так, будто загружает весь объем данных. Почему это происходит?
ОсновнаяТаблица = ТаблицаРегистра, платформа формирует запрос к СУБД. Если в регистре много измерений, ресурсов, или используются виртуальные таблицы (например, срез последних), запрос может стать очень сложным. СУБД, в свою очередь, может выбрать неоптимальный план выполнения, который игнорирует преимущества динамического считывания.ОсновнаяТаблица или КлючевыеПоля, платформа может не иметь достаточно информации для эффективного постраничного считывания, что также может приводить к загрузке больших объемов данных.В ходе обсуждения были выявлены два очень важных диагностических признака, которые указывают на более глубокие проблемы, чем просто неоптимальная настройка динамического списка:
1. Чрезвычайно медленный запрос ВЫБРАТЬ ПЕРВЫЕ 1 КОЛИЧЕСТВО(*)
Автор сообщил, что даже запрос, предназначенный для получения количества записей в регистре, выполняется очень долго:
ВЫБРАТЬ ПЕРВЫЕ 1 КОЛИЧЕСТВО(*) ИЗ РегистрСведений
Такое длительное выполнение (сравнимое со временем открытия документа) даже такого простого запроса, как ВЫБРАТЬ ПЕРВЫЕ 1 КОЛИЧЕСТВО(*) на регистре с 777 миллионами записей, является критическим индикатором серьезных проблем на уровне СУБД. Это может указывать на:
2. Порядок измерений регистра сведений
Автор также уточнил, что "измерение регистра документ является последним по метаданным". Этот факт имеет прямое отношение к производительности:
Порядок следования измерений в регистре сведений напрямую влияет на то, как платформа 1С формирует и использует индексы базы данных. Индексы автоматически создаются с учетом этого порядка. Если измерение Документ, по которому, предположительно, происходит основной отбор, находится последним в списке измерений, то автоматически созданный кластерный индекс (если регистр непериодический и не является основным в составном индексе) или другие индексы могут быть неэффективны для запросов, начинающихся с отбора по этому измерению.
Для оптимальной работы рекомендуется размещать часто используемые для отборов и сортировок измерения в начале списка измерений регистра. Это позволит СУБД быстрее находить нужные данные.
Теперь, когда мы проанализировали потенциальные причины и диагностические признаки, давайте разберем конкретные шаги, которые помогут нам решить эту проблему.
Для начала нам необходимо точно понять, какой именно SQL-запрос генерирует 1С, сколько времени он выполняется на уровне СУБД, и какой план выполнения выбирает база данных. Для этого мы будем использовать инструменты профилирования:
SQL:BatchCompleted, RPC:Completed) и, что особенно важно, планы выполнения запросов.pg_stat_statements и EXPLAIN ANALYZE для PostgreSQL, Oracle SQL Developer для Oracle).Во время профилирования откроем проблемный документ. Анализируя логи профайлера, мы сможем увидеть реальный SQL-запрос, который отправляется в базу данных, и, главное, понять, почему СУБД тратит на него столько времени. Возможно, это будет полное сканирование таблицы (Table Scan) вместо использования индекса (Index Seek), что является явным признаком проблемы.
Даже если динамический список создается программно и использует ОсновнаяТаблица = ТаблицаРегистра, мы можем влиять на его поведение. Если мы создаем динамический список программно, у нас есть возможности для его детальной настройки:
ИЛИ, НЕ, ПОДСТРОКА, которые часто делают индексы бесполезными или вынуждают СУБД выполнять полное сканирование.ОсновнаяТаблица не дает нужного результата, можем попробовать использовать произвольный запрос. Однако здесь есть свои нюансы:
КлючевыеПоля или ОсновнаяТаблица: При использовании произвольного запроса, критически важно явно указать ОсновнаяТаблица или задать КлючевыеПоля. Без них платформа не сможет эффективно считывать данные порциями, что приведет к загрузке всего объема. Например, если мы фильтруем по Документу, наш запрос может выглядеть так:
ВЫБРАТЬ
РегистрСведений.Документ КАК Документ,
РегистрСведений.Измерение1,
РегистрСведений.Ресурс1
ИЗ
РегистрСведений КАК РегистрСведений
ГДЕ
РегистрСведений.Документ = &ДокументСсылка
Документ в качестве основного ключа для постраничной навигации, если он проиндексирован. Мы должны убедиться, что параметр &ДокументСсылка корректно передается в динамический список.Как мы выяснили из медленного запроса КОЛИЧЕСТВО(*) и порядка измерений, индексы играют здесь ключевую роль. Мы должны убедиться, что они настроены оптимально:
Документ в нашем случае) и происходит сортировка.Документ и Номенклатура), создадим композитный индекс (Документ, Номенклатура). Важно: порядок полей в композитном индексе имеет значение! Самые селективные поля (с наибольшим разнообразием значений) или поля, по которым чаще всего начинается отбор, должны идти первыми.Документ действительно является последним и часто используется для отбора, мы должны рассмотреть возможность его перемещения в начало списка измерений регистра. Это позволит платформе 1С автоматически создавать более эффективные индексы. Важно: изменение порядка измерений — это серьезная операция, требующая полного тестирования и, возможно, конвертации данных. Проводить ее нужно крайне осторожно и только после полного резервного копирования.4 миллиона записей на документ и 777 миллионов записей в регистре — это колоссальный объем данных. Даже самая лучшая индексация и оптимизация запросов могут оказаться недостаточными, если архитектура не рассчитана на такие нагрузки. Здесь мы должны задать себе несколько вопросов и рассмотреть фундаментальные изменения:
Если нам необходимо выполнить сложные вычисления или форматирование данных, которые зависят от значений из динамического списка, мы можем использовать событие ПриПолученииДанныхНаСервере для динамического списка (доступно начиная с платформы 8.3.10). Это позволяет нам:
Использование временных таблиц в запросах динамических списков может быть полезным, но только при одном условии: временные таблицы должны содержать заведомо небольшое количество записей. Если временная таблица сама по себе будет содержать миллионы записей, ее использование может привести к еще большей деградации производительности. Мы используем временные таблицы для предварительной фильтрации или агрегации, когда эти операции значительно сокращают объем данных перед основным запросом к динамическому списку, например, для выборки уникальных значений или предварительного расчета сумм.
В заключение, проблема медленного открытия документа с динамическим списком и огромными объемами данных в 1С — это комплексная задача. Ее решение требует системного подхода, начиная от глубокого профилирования запросов на уровне СУБД, оптимизации индексов, и заканчивая пересмотром архитектуры хранения данных. Только так мы сможем добиться приемлемой производительности и комфортной работы пользователей, превратив 20-минутное ожидание в комфортные секунды.