Регистры сведений 1С. Как это устроено.
Основная идея публикации — собрать в одном месте информацию о внутреннем устройстве такой абстрактной сущности, как «Регистр сведений 1С» и ответить на ряд вопросов:
Что происходит при записи регистра в различных режимах? Что такое на самом деле «СрезПервых» и «СрезПоследних»? Как оптимально выбрать структуру регистра?
Это та информация, владея которой, начинаешь лучше понимать как это работает и как правильно использовать регистры сведений.
- Описание
- Подробнее
Описание
Публикация имеет характер исследования, поэтому подробная и объемная. Кто не любит много букв — можно начать с выводов, они специально выделены в содержании.
Для тех, кто только делает первые шаги в 1С: не смотря на подробность изложенной информации и её справочно-обучающую интонацию, тут нет самых азов. Подразумевается, что читатель уже имеет базовое понимание и практику конфигурирования в 1С. Статья не учит как программировать, но она помогает найти ответы на вопросы «А как правильно и почему именно так?».
Для тех, кто все это знает: возможно, у вас есть свои выводы и своя точка зрения, делитесь ими в коментах. Спасибо!
1. Архитектура регистра на уровне СУБД.
— индексы непериодического, независимого регистра сведений
— индексы непериодического, подчиненного РС
— индексы периодического, независимого РС
— индексы периодического, подчиненного РС
— индексы периодического РС с периодичностью «По позиции регистратора»
— индексы таблицы итогов среза первых и среза последних
2. Разбираемся с записью регистров
Независимые регистры сведений.
Подчиненные регистры сведений.
— запись с замещением и признаком обмена данными
— запись без замещения с признаком обмена данных
— подчиненный РС с периодичностью по позиции регистратора
Промежуточные выводы. Сравниваем 8.2 и 8.3, независимые и подчиненные регистры.
— запись с замещением («по умолчанию»)
подчиненные регистры с таблицей итогов
3. Как работает СрезПоследних (СрезПервых) в запросе
срез последних на языке 1С для регистра с периодичностью <> по позиции регистратора
срез последних на языке 1С для регистра с периодичность «По позиции регистратора»
самая частая ошибка при фильтрации среза
отличия 8.2 и 8.3 для запросов среза
когда используется таблица итогов
Все примеры будут даны для версий 1С 8.3.6 — 8.3.8. На 8.2.19 логика на 99% совпадает с работой 8.3, есть несколько отличий, про которые обязательно упомяну.
Работа платформы с регистрами сведений несколько раз менялась. 8.3 стала более оптимальной и как бы мне не хотелось «потыкать палочкой» в 8.1 и в ранние версии 8.2, дабы показать как все было плохо, решил этого не делать. Кому станет любопытно «как было» — получит мотивацию изучить вопрос.
Вводная.
Основное назначение регистров сведений — хранить информацию НЕ ссылочного типа в разрезе комбинации измерений и, как частный случай, хранить изменяемые во времени значения. По большому счету, в регистре можно хранить что угодно, но получить ссылку на саму запись регистра и сохранить её (ссылку на запись) в реквизитах другого объекта, например справочника, уже не получится. Собственно отличие ссылочных типов от не ссылочных — это один из краеугольных камней 1С т.ч. кто прогуливал — учим мат часть.
1. Архитектура регистра на уровне СУБД.
Спустимся с уровня абстракции «конфигуратор» на уровень «СУБД» и вспомним, в очередной раз, что все данные базы хранятся именно в СУБД. Это может быть файловая база (тут в роли СУБД платформа 1С), PosgreSQL, IBM DB2, Oracle и MS SQL Server.
Регистр сведений на уровне СУБД представляет собой обычную плоскую таблицу, в которой колонки это наши измерения, ресурсы и реквизиты, а строки — записи регистра. Узнать какая таблица СУБД соответствует конкретному регистру, можно используя метод платформы ПолучитьСтруктуруХраненияБазыДанных(), либо воспользоваться одной из множества обработок, уже опубликованных на INFOSTART.
Отличия ресурсов от реквизитов на уровне хранения данных отсутствуют, это сугубо логическое разделение. Предполагается, что реквизит это некая дополнительная информация, а ресурс — основное значение, которое нам и требуется хранить в разрезе комбинаций измерений.
Отличие измерений от ресурсов и реквизитов в том, что измерения в полном составе присутствуют во всех индексах таблицы. Порядок следования измерений в индексе такой же, как в конфигураторе. Если у ресурса (реквизита) установлено свойство «Индексировать», то будет создан индекс, в котором на первом месте этот ресурс (реквизит), а далее все наши измерения. Установить свойство «Индексировать» можно и у измерения, в этом случае будет создан дополнительный индекс, в котором на первом месте «проиндексированное» поле, а следом за ним оставшиеся измерения.
До версии 8.2.15 непериодический регистр сведений не имел кластерного индекса, начиная с этой версии, платформа создает кластерный индекс, состоящий из измерений (в том порядке, как они заданы в конфигураторе).
Версия 8.3 принесла еще несколько важных изменений:
- для периодических регистров кластерным стал индекс, в котором сначала следуют все измерения, а на последнем месте колонка Период (в 8.2 кластерным будет являться индекс, в котором на первом месте стоит Период, а затем перечислены все измерения);
- появились физические таблицы итогов для хранения среза первых и среза последних. Создавать или нет эти таблицы — решает разработчик, установив соответствующее свойство в конфигураторе.
Давайте посмотрим, какие индексы создаются в зависимости от версии платформы, периодичности и подчиненности регистра. Сразу оговорюсь, что информация на ИТС не точна в части кластерных индексов, верить написанному ниже:
Непериодический, независимый регистр
| Индекс | Условие и описание | Кластерный |
| Измерение1 + [Измерение2 +…] | Есть хоть одно измерение регистра. Индекс, включающий все измерения в том порядке, в котором они заданы при конфигурировании. | начиная с 8.2.15 и 8.3 |
| ИзмерениеN + Измерение1 + [Измерение2 +…] | Измерению «ИзмерениеN» задано свойство «Индексировать» или свойство «Ведущее» и при этом это не первое и не единственное измерение. Первое поле — ИзмерениеN, затем все остальные измерения в том порядке, в котором они заданы при конфигурировании. | — |
| Реквизит + Измерение1 + [Измерение2 +…] | Реквизиту «Реквизит» задано свойство «Индексировать». Индекс, в котором первое поле — Реквизит, затем все измерения в том порядке, в котором они заданы при конфигурировании. | — |
| Ресурс + Измерение1 + [Измерение2 +…] | Ресурсу «Ресурс» задано свойство «Индексировать». Индекс, в котором первое поле — Ресурс, затем все измерения в том порядке, в котором они заданы при конфигурировании. | — |
| SimpleKey (удалено в 8.3.3 и старше) | Количество измерений больше одного. Используется для обхода регистра при реструктуризации, а также для выборки записей с использованием оптимального порядка обхода. | — |
Непериодический, подчиненный регистр
| Индекс | Условие и описание | Кластерный |
| Регистратор + НомерСтроки | Создается всегда. | Да, всегда |
| Измерение1 + [Измерение2 +…] | Есть хоть одно измерение регистра. | — |
| ИзмерениеN + Измерение1 + [Измерение2 +…] | Измерению «ИзмерениеN» задано свойство «Индексировать» или свойство «Ведущее» и при этом это не первое и не единственное измерение | — |
| Реквизит + Измерение1 + [Измерение2 +…] | Реквизиту «Реквизит» задано свойство «Индексировать». | — |
| Ресурс + Измерение1 + [Измерение2 +…] | Ресурсу «Ресурс» задано свойство «Индексировать». | — |
| SimpleKey (удалено в 8.3.3 и старше) | Количество измерений больше одного. Используется для обхода регистра при реструктуризации, а также для выборки записей с использованием оптимального порядка обхода. | — |
Периодический, независимый регистр
| Индекс | Условие и описание | Кластерный |
| Период + [Измерение1 + …] | Создается всегда. | для 8.2 |
| Измерение1 + [Измерение2 +…] + Период | Есть хоть одно измерение регистра. | для 8.3 |
| ИзмерениеN + Период + Измерение1 + [Измерение2 +…] | Измерению «ИзмерениеN» задано свойство «Индексировать» или свойство «Ведущее» и при этом это не единственное измерение. | — |
| Реквизит + Период + [Измерение1 + …] | Реквизиту «Реквизит» задано свойство «Индексировать». | — |
| Ресурс + Период + [Измерение1 + …] | Ресурсу «Ресурс» задано свойство «Индексировать». | — |
Периодический, подчиненный регистр
| Индекс | Условие и описание | Кластерный |
| Регистратор + НомерСтроки | Создается всегда. | — |
| Период + [Измерение1 + …] + [Активность]* | Создается всегда. | для 8.2 |
| Измерение1 + [Измерение2 +…] + Период + [Активность]* | Есть хоть одно измерение регистра. | для 8.3 |
| ИзмерениеN + Период + Измерение1 + [Измерение2 +…] + [Активность]* | Измерению «ИзмерениеN» задано свойство «Индексировать» или свойство «Ведущее» и при этом это не единственное измерение. | — |
| Реквизит + Период + [Измерение1 + …] + [Активность]* | Реквизиту «Реквизит» задано свойство «Индексировать». | — |
| Ресурс + Период + [Измерение1 + …] | Ресурсу «Ресурс» задано свойство «Индексировать». | — |
* только для 8.3
Периодический, с периодичностью «По позиции регистратора»
| Индекс | Условие и описание | Кластерный |
| Период + Регистратор + НомерСтроки | Создается всегда. | для 8.2 |
| Регистратор + НомерСтроки | Создается всегда. | — |
| Измерение1 + [Измерение2 + …] + Период + Регистратор + НомерСтроки + [Активность]* | Есть хоть одно измерение регистра. | для 8.3 |
| Измерение + Период + Регистратор + НомерСтроки + [Активность]* | Измерению «Измерение» задано свойство «Индексировать». | — |
| Реквизит + Период + Регистратор + НомерСтроки + [Активность]* | Реквизиту «Реквизит» задано свойство «Индексировать». | — |
| Ресурс + Период + Регистратор + НомерСтроки | Ресурсу «Ресурс» задано свойство «Индексировать». | — |
* только для 8.3
Индексы таблицы итогов среза первых и среза последних. Только для 8.3.
| Индекс | Условие и описание | Кластерный |
| Измерение1 + [Измерение2 + …] | Есть хоть одно измерение регистра. | — |
| Реквизит + [Измерение1 + …] | Реквизиту «Реквизит» задано свойство «Индексировать» | — |
| Ресурс + [Измерение1 + …] | Ресурсу «Ресурс» задано свойство «Индексировать» | — |
Замечание. Если вы в своей базе видите отличия от того, что приведено в таблицах, то, скорее всего, вы работаете в режиме совместимости с 8.2. Так же при переходе с 8.1 на 8.2 структура индексов сама не меняется, необходимо сделать реструктуризацию.
Можно сказать, что в 8.3 структура индексов продумана лучше — в индексы добавлена «Активность», использование в качестве кластерных индексов вида «Измерение1 + [Измерение2 +…] + Период» снижают ресурсоемкость запросов (это ни в коем разе не панацея, но ниже рассмотрим примеры запросов и еще раз затронем тему эффективности индексов). При этом к 8.3 есть и вопросы, например не понятно, почему при индексировании ресурса в периодическом регистре в индекс не добавляется «Активность» и почему нет кластерного индекса в таблицах срезов.
- Порядок измерений, заданный в конфигураторе, влияет на структуру индексов и, как следствие, может влиять на скорость выборки данных. Дело в том, что индекс «не работает» если нет фильтра по первому его полю, при этом поля, по которым накладываются фильтры, должны идти в индексе друг за другом.
Например, есть непериодический, независимый регистр со следующими измерениями: Организация, Склад, Номенклатура. В СУБД получаем таблицу с одним индексом Организация + Склад + Номенклатура. Теперь рассмотрим различные варианты запросов к этому регистру:
- запрос с условием отбора только по Номенклатуре …ГДЕ Номенклатура = &Номенклатура — индекс «работать» не будет.
- запрос с фильтром …ГДЕ Склад = &Склад И Номенклатура = &Номенклатура — индекс так же не будет «работать» т.к. и в том и в другом случае нет отбора по Организации.
- запрос с отбором …ГДЕ Организация = &Организация И Номенклатура = &Номенклатура — индекс будет работать, но не эффективно — все данные по Организации будут получены быстро, но потом все они будут просканированы (построчно просмотрены), проверяя та ли Номенклатура в этой строке. А т.к. организаций обычно всего одна, а Номенклатур очень много, то прочитаны будут все строки регистра.
Для этого набора запросов самым оптимальным будет поменять местами измерения Организация и Номенклатура (получим индекс Номенклатура + Склад + Организация), тогда вопрос с эффективным использованием индекса будет только для запроса …ГДЕ Организация = &Организация И Номенклатура = &Номенклатура. Если в базе только одна организация, то индекс можно назвать подходящим т.к. условие по номенклатуре уже вернет малое число строк, которые очень быстро проверятся на соответствие условию по организации. Если организаций много, то правильным решением будет дополнительно создать индекс Организация + Номенклатура [+ Склад].
Итоговый универсальный вариант: измерения в порядке следования Номенклатура, Склад, Организация, у измерения Организация ставим свойство Индексировать.
Из этого примера можно сделать очень интересный вывод — спроектировать оптимальную архитектуру регистра можно только при известном пуле запросов, которые будут к нему обращаться, и понимании как будут распределяться данные!

