Как быстро выбрать подчиненные документы прямым SQL-запросом в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При оптимизации учетных систем на платформе 1С:Предприятие 7.7 с использованием прямого доступа к базе данных MS SQL разработчики часто сталкиваются с задачей выборки подчиненных документов. Попытка отфильтровать документы с помощью строковых функций вроде SUBSTRING() приводит к катастрофическому падению производительности. Разберем по шагам, почему это происходит, как устроен индекс таблицы связей и как составить быстрый SQL-запрос для одного документа или целого списка.

Выясним причину медленной работы запроса

В базе данных 1С 7.7 информация о связях подчиненности хранится в системной таблице _1SCRDOC. Для ускорения поиска по этой таблице создан составной индекс PARENT, включающий следующие поля:

  1. MDID — идентификатор реквизита отбора (графы отбора);
  2. PARENTVAL — 23-символьное типизированное строковое представление документа-родителя;
  3. CHILDDATE — дата подчиненного документа;
  4. CHILDTIME — время подчиненного документа;
  5. CHILDID — 9-значный 36-ричный идентификатор (IDDOC) подчиненного документа.

Когда в секции WHERE мы применяем функцию к индексированному полю (например, SUBSTRING(Подчиненные.PARENTVAL, 7, 9)), СУБД теряет возможность использовать индекс (нарушается условие SARGability). Вместо мгновенного поиска по индексу SQL Server выполняет полное сканирование таблицы (Table Scan / Index Scan), перебирая миллионы записей.

Вторая распространенная ошибка — отсутствие или некорректное указание первого поля индекса MDID. Если первое поле составного индекса не участвует в условии фильтрации, индекс по последующим полям также не может работать эффективно.

Правильная фильтрация по полю MDID

Поле MDID в таблице _1SCRDOC имеет тип CHAR(4). Для системных связей подчиненности (документ-основание) значение этого поля всегда равно нулю, дополненному тремя пробелами слева: ' 0'.

Важно: Нельзя писать MDID = 0 без кавычек, так как при неявном приведении типов строковое поле преобразуется в число, что снова приведет к игнорированию индекса. Необходимо всегда передавать точное строковое значение с пробелами:


WHERE Подчиненные.MDID = '   0'
  AND Подчиненные.PARENTVAL = :ВыбДокумент

Формат 23-значной строки PARENTVAL

Чтобы выполнить точный поиск по полю PARENTVAL, проанализируем его внутреннюю структуру. Полная строка длиной в 23 символа формируется по жестким правилам платформы 1С 7.7:

  1. Символы 1–2: Код типа объекта. Для типизированного документа это всегда O1 (латинская буква 'O' и цифра 1).
  2. Символы 3–6: 4-значный 36-ричный идентификатор вида документа (IDDOCDEF из таблицы _1SJOURN), выровненный по правому краю с пробелами слева.
  3. Символы 7–15: 9-значный 36-ричный идентификатор самого документа (IDDOC).
  4. Символы 16–23: 8 завершающих пробелов (заполнитель до фиксированной длины).

Если мы формируем значение прямо в SQL-запросе при выборке из журнала _1SJOURN, склейка полного представления выглядит следующим образом:


'O1' + RIGHT(SPACE(4) + CAST(Журнал.IDDOCDEF AS VARCHAR(4)), 4) + Журнал.IDDOC + SPACE(8)

Выборка подчиненных документов по списку

Рассмотрим, как быстро выбрать подчиненные документы для целого списка документов. При использовании внешних компонент для прямых запросов (например, 1С++) список документов выгружается во временную таблицу методом УложитьСписокОбъектов(), который автоматически генерирует поле Val с правильной 23-значной строкой.

Посмотрим на пример эффективного запроса, использующего соединение по индексу вместо медленного оператора IN:


Запрос = СоздатьОбъект("ODBCRecordset");
Запрос.УложитьСписокОбъектов(СписокРодительскихДокументов, "#ВыбДокументы", "Документ");

ТекстЗапроса = "
|SELECT 
|    Журнал.IDDOC AS [Документ $Документ],
|    Журнал.IDDOCDEF AS [Документ_вид]
|FROM 
|    _1SCRDOC AS Подчиненные WITH (NOLOCK)
|INNER JOIN 
|    #ВыбДокументы AS СписокРодителей ON Подчиненные.PARENTVAL = СписокРодителей.Val
|INNER JOIN 
|    _1SJOURN AS Журнал WITH (NOLOCK) ON Журнал.IDDOC = Подчиненные.CHILDID
|WHERE 
|    Подчиненные.MDID = '   0'
|    AND Журнал.ISMARK = 0
|";

Особенности и ограничения таблицы _1SCRDOC

При работе с подчиненными документами через прямые запросы обратим внимание на следующие нюансы:

  1. Только системная подчиненность: Таблица _1SCRDOC фиксирует только те связи, которые создаются платформенным механизмом ввода на основании. Если в конфигурации связь между документами реализована через произвольный реквизит шапки, такие документы в _1SCRDOC не отображаются.
  2. Проверка статуса документа: Поле CHILDID содержит только идентификатор документа без сведений о его проведении или пометке на удаление. Для исключения удаленных объектов обязательно соединяем выборку с _1SJOURN и проверяем условие ISMARK = 0.
← На главную