В мире 1С:Предприятие два понятия часто становятся источником путаницы — ссылка и объект. На первый взгляд они кажутся взаимозаменяемыми: оба позволяют работать с данными справочников, документов или регистров. Но на практике их неправильное использование приводит к ошибкам в коде, падению производительности или даже потере данных. Эта статья не просто перечислит различия, а покажет, как именно они проявляются в реальных задачах — от простого получения данных до сложных транзакций.
Чтобы понять разницу, представьте библиотеку. Ссылка — это библиографическая карточка с названием книги и её местоположением на полке. Она легковесная, её можно быстро передать другому читателю. Объект — сама книга со всеми страницами, закладками и пометками. Его нужно нести осторожно, а изменения в нём отразятся на оригинале. Теперь перенесём эту аналогию в 1С: когда вы работаете со ссылкой, вы манипулируете только "адресом" данных, а при работе с объектом — загружаете все его свойства и реквизиты в оперативную память.
В этой статье мы разберём:
- 🔹 Техническую основу ссылок и объектов в платформе 1С
- 🔹 Когда и почему нужно использовать каждый из них
- 🔹 Типичные ошибки, ведущие к утечкам памяти и зависанию базы
- 🔹 Примеры кода с пояснениями для разных версий платформы
1. Что такое ссылка в 1С: определение и внутренняя структура
Ссылка в 1С:Предприятие — это уникальный идентификатор объекта метаданных (справочника, документа, плана обмена и т.д.), который позволяет на него ссылаться без загрузки всех данных. Физически ссылка представляет собой комбинацию:
- 📌 Типа объекта (например,
СправочникСсылка.Номенклатура) - 📌 Уникального идентификатора (UID) — внутреннего кода, присваиваемого платформой
- 📌 Ссылки на базу данных (для распределённых информационных баз)
Главное преимущество ссылок — их минимальное потребление памяти. Когда вы передаёте ссылку в параметре функции или сохраняете её в реквизите, платформа копирует только этот идентификатор, а не все данные объекта. Например, при выборке 10 000 позиций номенклатуры из справочника в массив ссылок расход памяти будет в десятки раз меньше, чем при загрузке полных объектов.
Ссылки делятся на два типа:
- 🔗 Пустые ссылки (
СправочникСсылка.ПустаяСсылка()) — не указывают на реальный объект, часто используются для инициализации переменных. - 🔗 Заполненные ссылки — содержат UID и позволяют получить объект по методу
ПолучитьОбъект().
⚠️ Внимание: Ссылки на удалённые объекты (помеченные на удаление) остаются валидными до момента физического удаления из базы. Проверяйте их актуальность через метод ЭтоУдаленный() перед использованием.
2. Объект в 1С: когда данные "материализуются"
Объект — это полноценная копия данных из базы, загруженная в оперативную память. В отличие от ссылки, он содержит:
- 📄 Все реквизиты (включая составные типы)
- 📄 Табличные части с детализацией
- 📄 Динамические списки и связанные коллекции
- 📄 Модули объекта (если применимо)
Объекты создаются:
- 🛠️ Явно — через
Справочники.Номенклатура.СоздатьЭлемент()илиДокументы.ЗаказПокупателя.СоздатьДокумент() - 🛠️ Неявно — при вызове
ПолучитьОбъект()у ссылки или при выборке данных с флагомЗагружатьОбъекты = Истина
Работа с объектами требует больше ресурсов, но даёт полный контроль над данными. Например, только через объект можно:
- 🔧 Изменить реквизит:
Объект.Наименование = "Новое значение" - 🔧 Добавить строку в табличную часть:
Объект.Товары.Добавить() - 🔧 Вызвать метод модуля:
Объект.РассчитатьСумму()
Если вам нужно только прочитать значение реквизита, используйте ссылку с методом ПолучитьРеквизит("Наименование") — это в 3-5 раз быстрее, чем загрузка полного объекта.
| Характеристика | Ссылка | Объект |
|---|---|---|
| Потребление памяти | Минимальное (только UID) | Высокое (все реквизиты + табличные части) |
| Скорость создания | Мгновенно | Зависит от размера объекта |
| Возможность изменения | Нет (только чтение) | Да (с последующей записью) |
| Методы работы | ПолучитьОбъект(), ЭтоУдаленный() |
Записать(), УстановитьНовый(), реквизиты как свойства |
| Использование в запросах | Да (как параметр) | Нет (требует предварительной записи) |
3. Ключевые отличия: когда что использовать
Выбор между ссылкой и объектом зависит от цели операции. Вот чек-лист для принятия решения:
Используйте ССЫЛКУ, если:|Нужно передать идентификатор объекта в функцию|Требуется только чтение данных без изменений|Работаете с большими выборками (оптимизация памяти)
Используйте ОБЪЕКТ, если:|Нужно изменить реквизиты или табличные части|Вызываете методы модуля объекта|Работаете в транзакции с последующей записью-->
Типичные сценарии использования ссылок:
- 🔍 Поиск и фильтрация данных (например, в отчётах)
- 🔍 Передача параметров между функциями
- 🔍 Хранение связей в реквизитах других объектов
Примеры, когда объекты необходимы:
- 📝 Создание новых документов или элементов справочников
- 📝 Модификация существующих данных
- 📝 Выполнение расчётов с использованием методов объекта
Почему нельзя изменять данные через ссылку?
Ссылка — это лишь "указатель" на объект в базе. Она не содержит сами данные, поэтому платформа 1С не позволяет модифицировать реквизиты напрямую. Для изменений требуется загрузить полный объект в память, что гарантирует:
1. Консистентность данных (проверка заполнения обязательных реквизитов)
2. Возможность отката при ошибках (транзакции)
3. Выполнение триггеров и обработчиков событий.
4. Производительность: что быстрее и почему
Разница в производительности между ссылками и объектами становится критичной при работе с большими объёмами данных. Рассмотрим тестовый сценарий: выборка 10 000 элементов справочника Номенклатура.
При использовании ссылок:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Ссылка ИЗ Справочник.Номенклатура";
Результат = Запрос.Выполнить().Выгрузить(); // ~0.5 секунды
Платформа возвращает только массивы UID, без загрузки реквизитов.
При загрузке объектов:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Ссылка ИЗ Справочник.Номенклатура";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект(); // ~15-20 секунд
КонецЦикла;
Каждый вызов ПолучитьОбъект() инициирует чтение всех реквизитов из базы.
⚠️ Внимание: В клиент-серверном варианте работы 1С загрузка объектов по ссылкам вызывает дополнительные сетевые запросы к серверу. Это может стать узким местом при медленном соединении.
5. Типичные ошибки и как их избежать
Ошибка №1: Загрузка объектов в цикле без необходимости
Антипример:
Для Каждого Строка Из ТаблицаТоваров Цикл
Товар = Справочники.Номенклатура.НайтиПоНаименованию(Строка.Наименование).ПолучитьОбъект(); // Лишняя загрузка!
Сообщить(Товар.Артикул);
КонецЦикла;
Исправление: Используйте ПолучитьРеквизит("Артикул") напрямую у ссылки.
Ошибка №2: Хранение объектов в коллекциях
Если вы сохраняете объекты в Массив или Структура на длительное время, это приводит к:
- 🗑️ Утечкам памяти (объекты остаются в памяти даже после использования)
- 🗑️ Конфликтам блокировок (если объекты не освобождены правильно)
Ошибка №3: Игнорирование транзакций при работе с объектами
Пример опасной операции:
Док = Документы.ЗаказПокупателя.СоздатьДокумент();
Док.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");
Док.Записать(); // Без транзакции!
Риск: При сбое после записи документ останется в базе в некорректном состоянии.
Исправление: Оберните в транзакцию:
НачатьТранзакцию();
Попытка
Док = Документы.ЗаказПокупателя.СоздатьДокумент();
Док.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");
Док.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Всегда освобождайте объекты после использования, особенно в циклах! Используйте конструкцию Объект = Неопределено; или ОчиститьОжидание(); для принудительной очистки памяти.
6. Практические примеры: от простого к сложному
Пример 1. Получение данных без загрузки объекта
Задача: Вывести наименование и артикул номенклатуры в отчёт, не загружая полный объект.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Результат = Запрос.Выполнить().Выгрузить();
Здесь мы получаем все нужные данные одним запросом, без дополнительных обращений к базе.
Пример 2. Массовое создание документов
Задача: Создать 100 заказов покупателя на основе данных из файла. Неправильно:
Для Каждого Строка Из ДанныеИзФайла Цикл
Док = Документы.ЗаказПокупателя.СоздатьДокумент(); // Создаём объект в цикле!
Док.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию(Строка.Контрагент);
Док.Записать();
КонецЦикла;
Правильно:
// Подготавливаем ссылки на контрагентов заранее
Контрагенты = Новый Соответствие;
Для Каждого Строка Из ДанныеИзФайла Цикл
Если НЕ Контрагенты.Получить(Строка.Контрагент) Тогда
Контрагенты.Вставить(Строка.Контрагент, Справочники.Контрагенты.НайтиПоНаименованию(Строка.Контрагент));
КонецЕсли;
КонецЦикла;
// Создаём документы
НачатьТранзакцию();
Попытка
Для Каждого Строка Из ДанныеИзФайла Цикл
Док = Документы.ЗаказПокупателя.СоздатьДокумент();
Док.Контрагент = Контрагенты.Получить(Строка.Контрагент); // Используем готовую ссылку
Док.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Выигрыш: Сокращение количества обращений к базе в 100 раз (один поиск контрагента вместо 100).
Пример 3. Работа с удалёнными объектами
Задача: Проверить, не удалена ли номенклатура перед добавлением в документ.
Функция ПроверитьАктуальностьНоменклатуры(СсылкаНаНоменклатуру)
Если СсылкаНаНоменклатуру.ЭтоУдаленный() Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции;
Важно: Метод ЭтоУдаленный() работает только со ссылками, а не с объектами!
7. Особенности в разных версиях 1С
Платформа 1С:Предприятие эволюционирует, и работа со ссылками/объектами тоже претерпела изменения:
| Версия платформы | Изменения в работе со ссылками/объектами |
|---|---|
| 8.0-8.1 | Отсутствие метода ПолучитьРеквизит() у ссылок — приходилось загружать объект даже для чтения. |
| 8.2 | Появление ПолучитьРеквизит(), но работа с динамическими списками ещё не оптимизирована. |
| 8.3.6+ | Введены управляемые блокировки для объектов, улучшена работа с большими выборками ссылок. |
| 8.3.18+ | Оптимизирована память при работе с массивами ссылок (уменьшено дублирование UID). |
В 1С:Предприятие 8.3.20+ появилась возможность использовать отложенную загрузку объектов через механизм ПланыОбмена. Это позволяет:
- 🔄 Отложить загрузку полных данных до момента реальной необходимости
- 🔄 Снизить нагрузку на сеть в распределённых базах
⚠️ Внимание: В версиях ниже 8.3.10 метод СравнитьСсылок() может работать некорректно с ссылками на объекты из разных баз в распределённой системе. Всегда проверяйте актуальность механизмов синхронизации.
FAQ: Частые вопросы по ссылкам и объектам в 1С
Можно ли преобразовать объект обратно в ссылку?
Да, у любого объекта есть свойство Ссылка, которое возвращает его ссылку. Пример:
Объект = Справочники.Номенклатура.СоздатьЭлемент();
Объект.Наименование = "Тестовый товар";
СсылкаНаОбъект = Объект.Ссылка; // Получаем ссылку до записи!
Важно: Ссылка будет пустой (ПустаяСсылка()), если объект ещё не записан в базу.
Почему при сравнении двух ссылок на один объект возвращается Ложь?
Это типичная ошибка при работе с распределёнными базами. Ссылки считаются равными только если:
- 🔹 Они указывают на один и тот же объект в одной базе данных
- 🔹 Имеют одинаковый
UID(внутренний идентификатор)
Для сравнения ссылок из разных баз используйте реквизиты (например, Наименование или Код).
Если Ссылка1.УникальныйИдентификатор() = Ссылка2.УникальныйИдентификатор() Тогда
// Ссылки указывают на один объект
КонецЕсли;
Как узнать, какой тип объекта скрывается за ссылкой?
Используйте метод ТипЗначения() или свойство Метаданные():
ТипСсылки = ТипЗначения(Ссылка); // Вернёт, например, "СправочникСсылка.Номенклатура"
ИмяСправочника = Ссылка.Метаданные().Имя; // Вернёт "Номенклатура"
Для документов аналогично работает Ссылка.Метаданные().Имя.
Можно ли изменить реквизит объекта через ссылку?
Нет, это принципиально невозможно. Ссылка — это лишь указатель. Для изменения данных необходимо:
- Получить объект по ссылке (
ПолучитьОбъект()) - Изменить реквизит
- Записать объект (
Записать())
Что быстрее: получить объект по ссылке или найти его по реквизитам?
Получение объекта по существующей ссылке всегда быстрее, чем поиск по реквизитам (например, по наименованию). Сравнение:
- 🔹
Объект = Ссылка.ПолучитьОбъект()— ~0.001 сек (одно обращение к кешу) - 🔹
Объект = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1")— ~0.05-0.2 сек (полнотекстовый поиск)