При проектировании структуры данных в 1С часто возникает дилемма: использовать для хранения информации справочник или регистр сведений. Распространено мнение, что регистр сведений работает быстрее за счет отсутствия служебных полей (таких как ссылка, код, наименование и пометка удаления). Однако на практике скорость выборки данных определяется не столько видом объекта метаданных, сколько физической структурой таблиц в СУБД, попаданием в индексы и характером выполняемого запроса.
Разберем детально, как устроены таблицы справочников и регистров сведений «под капотом», когда регистр сведений действительно дает преимущество в скорости и в каких случаях справочник не уступает или даже превосходит его.
Проанализируем, как платформа 1С организует хранение данных справочников и независимых непериодических регистров сведений на уровне СУБД (например, Microsoft SQL Server или PostgreSQL):
IDRRef). Сами данные физически упорядочены на диске именно по внутреннему идентификатору ссылки. Если мы выполняем поиск по произвольному реквизиту (даже если для него установлено свойство Индексировать), СУБД использует некластерный индекс. Некластерный индекс содержит значение реквизита и ссылку, после чего СУБД выполняет операцию поиска по закладке (Key Lookup / Bookmark Lookup) в кластерном индексе, чтобы дочитать остальные запрашиваемые поля. При выборке большого объема строк это приводит к дополнительным операциям случайного ввода-вывода (I/O).Clustered Index Seek), считывая сразу все ресурсы и реквизиты без дополнительных обращений к другим таблицам.Таким образом, при сплошном чтении диапазонов записей по ключевым полям регистр сведений выполняет меньше операций чтения с диска, чем справочник.
Рассмотрим ключевое архитектурное отличие, влияющее на скорость фильтрации по нескольким полям одновременно:
В регистре сведений автоматически формируется главный составной индекс по всем измерениям. Если нам требуется выполнить отбор по двум или трем полям одновременно, запрос к регистру сведений с условием по первым измерениям гарантированно использует один эффективный составной индекс.
Посмотрим на пример условия в запросе:
ГДЕ
Таблица.Поле1 = &Значение1
И Таблица.Поле2 = &Значение2
Если Таблица — это регистр сведений, а Поле1 и Поле2 являются его первыми измерениями, СУБД выполнит точечный поиск по составному индексу. Если же Таблица — это справочник, а поля — обычные реквизиты, ситуация меняется:
Владелец + Реквизит или Родитель + Реквизит).Index Intersection), что существенно уступает по скорости единому составному индексу.Сравним два типовых запроса на чтение данных при одинаковом составе полей.
Выборка из справочника:
ВЫБРАТЬ
Спр.Реквизит1 КАК Поле1,
Спр.Реквизит2 КАК Поле2,
Спр.Значение КАК Значение
ИЗ
Справочник.НоменклатураПараметры КАК Спр
ГДЕ
Спр.Реквизит1 = &Значение1
И Спр.Реквизит2 = &Значение2
Выборка из регистра сведений:
ВЫБРАТЬ
РС.Реквизит1 КАК Поле1,
РС.Реквизит2 КАК Поле2,
РС.Значение КАК Значение
ИЗ
РегистрСведений.НоменклатураПараметры КАК РС
ГДЕ
РС.Реквизит1 = &Значение1
И РС.Реквизит2 = &Значение2
Если в регистре сведений Реквизит1 и Реквизит2 являются измерениями (причем Реквизит1 идет первым в списке метаданных), второй запрос отработает стабильнее и быстрее на больших объемах данных (от сотен тысяч и миллионов записей).
Выясним, в каких случаях справочник может оказаться выгоднее регистра сведений:
НайтиПоСсылкам) предотвращает случайное удаление элементов, на которые завязаны документы и проводки. В регистре сведений контроль удаления записей необходимо реализовывать программно (например, через проверку флагов в свойстве ДополнительныеСвойства набора записей в обработчиках событий).Оценим разницу в операциях модификации данных:
РегистрСведенийНаборЗаписей выполняется значительно быстрее, чем создание аналогичного числа элементов справочника. При записи регистра не требуется генерировать уникальные идентификаторы (GUID), проверять уникальность кода, рассчитывать версию данных (ВерсияДанных) и обновлять объектный кэш.Подведем итог для выбора оптимального объекта метаданных:
Индексировать и по возможности используем фильтрацию по предопределенным составным индексам (например, по владельцу или родителю).