1c recordertref в sql что содержит

Обновлено: 03.07.2024

Варианты решения:

1. В SQL Server managment studio физически уничтожаем сбойный индекс (в моем случае это был индекс по таблице итогов регистра бухгалтерии). В 1С распроводим сбойные документы. В режиме тестирования и исправления ставим галки реиндексация таблиц + пересчет итогов. 1С воссоздает индекс уже без ошибки. Проводим ранее сбоившие документы.

2. 1) С помощью Management Studio 2005 сгенерировала create-скрипт на создание индекса, который глючил, и сохранила в файлик.
2) Вручную убила косячный индекс из таблицы _AccumRgTn19455
3) Запустила запрос вида
Код SQL
После того, как индекс был убит, у меня отобразилось 15 дублирующихся записей, хотя до выполнения п.2 запрос ничего не возвращал.
4) Просмотрела все записи и вручную почистила дубликаты. На самом деле, я ещё пользовалась обработкой "Структура отчёта", чтобы понять, с чем вообще имею дело. Оказалось, что в таблице _AccumRgTn19455 хранится регистр накопления "Выпуск продукции (налоговый учёт)". Я ещё поковырялась sql-запросами, выявила 15 неуникальных документов и после окончания всех действ проверила в 1С, что эти документы проводятся нормально, без ошибок. Просто так чистить таблицы наобум, конечно, не стоит: важно понимать, что чистится и чем это может обернуться.
5) Запустила запрос на создание индекса, который был сохранён в файле.
6) Перевела базу в однопользовательский режим и запустила dbcc checkdb - на этот раз ни одной ошибки не выдалось.
7) Перевела базу обратно в однопользовательский режим.
Всё. проблема побеждена. Ну ещё в 1С запустила "Тестирование и исправление", там тоже всё прошло нормально, перестало ругаться на неуникальный индекс.

3. Если неуникальность заключается в датах с нулевыми значениями, то проблема решается созданием базы с параметром смещения равным 2000.

1. Если проблема загрузкой базы данных, то:
1.1. Если Вы делаете загрузку (используйете dt-файл) в базу MS SQL Server, то при создании базы перед загрузкой укажите смещение дат - 2000.
Если уже база создана со смещением 0, то создайте новую с 2000.

1.2. Если есть возможность в файловом варианте работать с базой, то выполните Тестирование и Исправление, а также Конфигурация - Проверка конфигурации - Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.3. Если нет файлового варианта, попробуйте загрузить из DT в клиент-серверный вариант с DB2 (который менее требователен к уникальности), и затем выполнить Тестирование и Исправление, а также Конфигурация - Проверка конфигурации - Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.4. Для локализации проблемы можно определить данные объекта, загрузка которого не удалась. Для этого надо включить во время загрузки трассировку в утилите Profiler или включите запись в технологический журнал событий DBMSSQL и EXCP.

2. Если проблема неуникальности проявляется во время работы пользователей:

2.1. Найти с помощью метода пункта 1.4 проблемный запрос.

2.1.2. Иногда ошибка возникает во время исполнения запросов, например:

Данная ошибка возникает из-за того что в модуле регистра накопления "Рабочее время работников организаций" в процедуре "ЗарегистрироватьПерерасчеты" в запросе не стоит служебное слово "РАЗЛИЧНЫЕ".
Код 1C v 8.х
В последних выпущенных релизах ЗУП и УПП ошибка не возникает, т.к. там стоит "РАЗЛИЧНЫЕ".

2.2. После нахождения проблемного индекса из предыдущего пункта, необходимо найти неуникальную запись.
2.2.1. «Рыба» скрипта для определения неуникальных записей с помощью SQL:
Код SQL

2.2.2 Пример. Индекс в ошибке называется "_Document140_VT1385_IntKeyIndNG".
Перечень полей таблицы:
_Document140_IDRRef, _KeyField, _LineNo1386, _Fld1387, _Fld1388, _Fld1389, _Fld1390, _Fld1391RRef, _Fld1392RRef, _Fld1393_TYPE, _Fld1393_RTRef, _Fld1393_RRRef, _Fld1394,_Fld1395, _Fld1396RRef, _Fld1397, _Fld1398, _Fld1399RRef, _Fld22260_TYPE, _Fld22260_RTRef, _Fld22260_RRRef, _Fld22261_TYPE, _Fld22261_RTRef, _Fld22261_RRRef
Перед выполнением приведенной ниже процедуры сделайте резервную копию базы данных.
Выполните в MS SQL Server Query Analizer:
Код SQL
С его помощью узнайте значения колонок _Document140_IDRRef, _KeyField, дублирующихся записей (id, key).

При помощи запроса:
Код SQL
посмотрите на значения других колонок дублирующихся записей.
Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):
Код SQL
Замените значение _KeyField в одной из повторяющихся записей на правильное:
Код SQL
Здесь _LineNo1386 = - дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.

Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:
Код SQL
Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:
Код SQL

Описанную процедуру необходимо выполнить для каждой пары повторяющихся записей.

2.2.3. Второй пример:
Код SQL

2.3.4 Пример определения неуникальных записей с помощью запроса 1С:Предприятие:
Код 1C v 8.х

Начал еще раз разбираться с медленным восстановлением последовательности. Все упирается в использовании виртуальной таблицы регистра накопления Остатки.
Выполняю запрос получение на нужную дату в середине месяца старого года по одному измерению и одному ресурсу. Запрос во вложении.
Смотрю во что превращается запрос в Sql. Во вложении.
Там соединяется таблица итогов и часть основной таблицы. Все логично. Но если посмотреть на запрос из основной таблицы, то там есть избыточное условие:
(_Period = @P6) AND (_Period < @P8)
где @P6 выбранная мною дата, а @P8 это начало следующего месяца. Из-за этой избыточности и происходит торможение.
Если убрать (_Period < @P8), то запрос существенно ускоряется.

Можешь это вынести на партнерский форум?

Добавлено (15.11.2014, 21:38)
---------------------------------------------
Речь про выполнение запроса в транзакции при восстановлении последовательностей, потому там возникает дополнительное условие на регистратор, чего нет в при выполнение этого же запроса вне транзакции.

Оригинальное условие:
WHERE (T4._Period > @P5 OR T4._Period = @P6 AND (T4._RecorderTRef > 0x00000141 OR T4._RecorderTRef = 0x00000141 AND T4._RecorderRRef >= @P7)) AND T4._Period < @P8 AND T4._Active = 0x01

Если раскрыть скобки, то получается:
WHERE (_Period > @P5) AND (_Period < @P8) AND (_Active = 0x01) OR
(_Period = @P6) AND (_Period < @P8) AND (_Active = 0x01) AND (_RecorderTRef > 0x00000141) OR
(_Period = @P6) AND (_Period < @P8) AND (_Active = 0x01) AND (_RecorderTRef = 0x00000141) AND (_RecorderRRef >= @P7)

Причем @P6 заведомо меньше @P8

Профайлер дает следующие данные:
Оригинальное условие : Reads 45000 Duration 433
Раскрытые скобки : Reads 45000 Duration 500
Оптимизированное условие: xм, а теперь в 2 раза дольше

Почему-то оптимизированное условие медленне условия с раскрытыми скобками.
WHERE (_Period > @P5) AND (_Period < @P8) AND (_Active = 0x01) OR
(_Period = @P6) AND (_Active = 0x01) AND (_RecorderTRef > 0x00000141) OR
(_Period = @P6) AND (_Active = 0x01) AND (_RecorderTRef = 0x00000141) AND (_RecorderRRef >= @P7)

Добавлено (15.11.2014, 21:40)
---------------------------------------------
Тему можно закрыть, отбой вопроса, непонятно как-то

Варианты решения:

1. В SQL Server managment studio физически уничтожаем сбойный индекс (в моем случае это был индекс по таблице итогов регистра бухгалтерии). В 1С распроводим сбойные документы. В режиме тестирования и исправления ставим галки реиндексация таблиц + пересчет итогов. 1С воссоздает индекс уже без ошибки. Проводим ранее сбоившие документы.

2. 1) С помощью Management Studio 2005 сгенерировала create-скрипт на создание индекса, который глючил, и сохранила в файлик.
2) Вручную убила косячный индекс из таблицы _AccumRgTn19455
3) Запустила запрос вида
Код SQL
После того, как индекс был убит, у меня отобразилось 15 дублирующихся записей, хотя до выполнения п.2 запрос ничего не возвращал.
4) Просмотрела все записи и вручную почистила дубликаты. На самом деле, я ещё пользовалась обработкой "Структура отчёта", чтобы понять, с чем вообще имею дело. Оказалось, что в таблице _AccumRgTn19455 хранится регистр накопления "Выпуск продукции (налоговый учёт)". Я ещё поковырялась sql-запросами, выявила 15 неуникальных документов и после окончания всех действ проверила в 1С, что эти документы проводятся нормально, без ошибок. Просто так чистить таблицы наобум, конечно, не стоит: важно понимать, что чистится и чем это может обернуться.
5) Запустила запрос на создание индекса, который был сохранён в файле.
6) Перевела базу в однопользовательский режим и запустила dbcc checkdb - на этот раз ни одной ошибки не выдалось.
7) Перевела базу обратно в однопользовательский режим.
Всё. проблема побеждена. Ну ещё в 1С запустила "Тестирование и исправление", там тоже всё прошло нормально, перестало ругаться на неуникальный индекс.

3. Если неуникальность заключается в датах с нулевыми значениями, то проблема решается созданием базы с параметром смещения равным 2000.

1. Если проблема загрузкой базы данных, то:
1.1. Если Вы делаете загрузку (используйете dt-файл) в базу MS SQL Server, то при создании базы перед загрузкой укажите смещение дат - 2000.
Если уже база создана со смещением 0, то создайте новую с 2000.

1.2. Если есть возможность в файловом варианте работать с базой, то выполните Тестирование и Исправление, а также Конфигурация - Проверка конфигурации - Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.3. Если нет файлового варианта, попробуйте загрузить из DT в клиент-серверный вариант с DB2 (который менее требователен к уникальности), и затем выполнить Тестирование и Исправление, а также Конфигурация - Проверка конфигурации - Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.4. Для локализации проблемы можно определить данные объекта, загрузка которого не удалась. Для этого надо включить во время загрузки трассировку в утилите Profiler или включите запись в технологический журнал событий DBMSSQL и EXCP.

2. Если проблема неуникальности проявляется во время работы пользователей:

2.1. Найти с помощью метода пункта 1.4 проблемный запрос.

2.1.2. Иногда ошибка возникает во время исполнения запросов, например:

Данная ошибка возникает из-за того что в модуле регистра накопления "Рабочее время работников организаций" в процедуре "ЗарегистрироватьПерерасчеты" в запросе не стоит служебное слово "РАЗЛИЧНЫЕ".
Код 1C v 8.х
В последних выпущенных релизах ЗУП и УПП ошибка не возникает, т.к. там стоит "РАЗЛИЧНЫЕ".

2.2. После нахождения проблемного индекса из предыдущего пункта, необходимо найти неуникальную запись.
2.2.1. «Рыба» скрипта для определения неуникальных записей с помощью SQL:
Код SQL

2.2.2 Пример. Индекс в ошибке называется "_Document140_VT1385_IntKeyIndNG".
Перечень полей таблицы:
_Document140_IDRRef, _KeyField, _LineNo1386, _Fld1387, _Fld1388, _Fld1389, _Fld1390, _Fld1391RRef, _Fld1392RRef, _Fld1393_TYPE, _Fld1393_RTRef, _Fld1393_RRRef, _Fld1394,_Fld1395, _Fld1396RRef, _Fld1397, _Fld1398, _Fld1399RRef, _Fld22260_TYPE, _Fld22260_RTRef, _Fld22260_RRRef, _Fld22261_TYPE, _Fld22261_RTRef, _Fld22261_RRRef
Перед выполнением приведенной ниже процедуры сделайте резервную копию базы данных.
Выполните в MS SQL Server Query Analizer:
Код SQL
С его помощью узнайте значения колонок _Document140_IDRRef, _KeyField, дублирующихся записей (id, key).

При помощи запроса:
Код SQL
посмотрите на значения других колонок дублирующихся записей.
Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):
Код SQL
Замените значение _KeyField в одной из повторяющихся записей на правильное:
Код SQL
Здесь _LineNo1386 = - дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.

Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:
Код SQL
Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:
Код SQL

Описанную процедуру необходимо выполнить для каждой пары повторяющихся записей.

2.2.3. Второй пример:
Код SQL

2.3.4 Пример определения неуникальных записей с помощью запроса 1С:Предприятие:
Код 1C v 8.х

Есть регистр накопления остатков «РасчетыПоПриобретениюВВалютеОрганизации» со следующей структурой:

  1. Организация, типа справочник «Организации»
  2. Контрагент, типа справочник «Контрагенты»
  3. ДоговорКонтрагента, типа справочник «ДоговорыКонтрагентов»
  4. Сделка, типа документ «Счет на оплату поставщику»
  5. Счет оплаты, типа ПланыСчетов.Хозрасчетный
  6. ДокументРасчетовСКонтрагентом, типа документ поступления и оплаты…

Есть запрос по остатками этого регистра:

ЕСТЬNULL(СУММА(РасчетыПоПриобретениюВВалютеОрганизацииОстатки.СуммаВзаиморасчетовОстаток), 0) КАК СуммаВзаиморасчетовОстаток

И Сделка = &Сделка

И СчетОплаты = &СчетОплаты

И ДокументРасчетовСКонтрагентом = &ДокументРасчетовСКонтрагентом) КАК РасчетыПоПриобретениюВВалютеОрганизацииОстатки

Отборы по Организации и Контрагенту не устанавливаются, так как они однозначно определяются договором (справочник «ДоговорыКонтрагентов» подчинен справочнику «Контрагенты» и в нем есть реквизит «Организация»).

В отборе по периоду виртуальной таблицы используется момент времени – это документ с датой «01.11.2011 00:00:00»

Поймаем запрос в профайлере:

exec sp_executesql N'SELECT

ISNULL(CAST(CAST(SUM(T1.Fld22268Balance_) AS NUMERIC(38, 8)) AS NUMERIC(38, 8)),0.0)

CAST(SUM(T2.Fld22268Balance_) AS NUMERIC(38, 8)) AS Fld22268Balance_

ISNULL(CAST(CAST(SUM(T3._Fld22268) AS NUMERIC(33, 8)) AS NUMERIC(27, 2)),0.0) AS Fld22268Balance_

FROM _AccumRgT22270 T3

WHERE T3._Period = @P1

AND (((((T3._Fld22262RRef = @P2) AND (T3._Fld27856_TYPE = @P3)) AND (T3._Fld22264RRef = @P4)) AND (T3._Fld23634_TYPE = @P5 AND T3._Fld23634_RTRef = @P6 AND T3._Fld23634_RRRef = @P7)))

CAST(ISNULL(CAST(CAST(SUM(CASE WHEN T4._RecordKind = 0.0 THEN -T4._Fld22268 ELSE T4._Fld22268 END) AS NUMERIC(27, 8)) AS NUMERIC(21, 2)),0.0) AS NUMERIC(27, 2)) AS Fld22268Balance_

FROM _AccumRg22261 T4

WHERE (T4._Period > @P8 OR T4._Period = @P8 AND (T4._RecorderTRef > @P9 OR T4._RecorderTRef = @P9 AND T4._RecorderRRef >= @P10))

AND T4._Period < @P1

AND T4._Active = @P11

AND (((((T4._Fld22262RRef = @P2) AND (T4._Fld27856_TYPE = @P3)) AND (T4._Fld22264RRef = @P4)) AND (T4._Fld23634_TYPE = @P5 AND T4._Fld23634_RTRef = @P6 AND T4._Fld23634_RRRef = @P7)))

@P1 datetime, @P2 varbinary(16), @P3 varbinary(1), @P4 varbinary(16),

@P5 varbinary(1), @P6 varbinary(4), @P7 varbinary(16), @P8 datetime,

@P9 varbinary(4), @P10 varbinary(16), @P11 varbinary(1)',

, 0xB5B202BFAC10409211E033900477750B, 0x01, 0x8596608F1DCF9AE642B3C7529403EE34,

0x08, 0x00000111, 0xB1B202BFAC10409211E117376ABAD6C1, ,

0x00000170, 0x8D0F02BFAC10409211E1219D93CB1649, 0x01

Видим, что виртуальная таблица «Остатки» преобразовалась в агрегатный («SUM(T1.Fld22268Balance_)») запрос с вложенным объединением («UNION ALL») двух запросов.

Разберем первый запрос в объединении:

Первый запрос выполняется к таблице итогов регистра («FROM _AccumRgT22270 T3»). Данные в таблице итогов хранятся по каждому месяцу (поле «_Period») в разрезе всех измерений и ресурсов. В секции «WHERE» устанавливается отбор по месяцу итогов («WHERE T3._Period = @P1») и всем измерениям, указанным в параметрах отбора виртуальной таблицы. Обратим внимание, что параметр «@P1» равен , то есть 01.12.2011 00:00:00 (используется смещение дат 2000), а запрос Мы выполняем на 01.11.2011 00:00:00… То есть итоги выбираются по состоянию на следующий месяц…

Разберем второй запрос в объединении:

Второй запрос выполняется к таблице движений регистра («FROM _AccumRg22261 T4»).

В секции «WHERE» устанавливается отбор по моменту времени («WHERE (T4._Period > @P8 OR T4._Period = @P8 AND (T4._RecorderTRef > @P9 OR T4._RecorderTRef = @P9 AND T4._RecorderRRef >= @P10))»).

Вспомним что момент времени это «период плюс ссылка». Ссылка – это тип ссылки («_RecorderTRef») и собственно сама ссылка («_RecorderRRef»). Отбор по моменту времени выполняется по условию «Больше или равно». Момент времени, используемый как отбор по периоду виртуальной таблицы, задается параметрами @P8, @P9, @P10.

Дальше через «И» в секции «WHERE» задается условие «AND T4._Period < @P1», где @P1 равен – это период на который Мы выбирали итоги из таблицы итогов в первом запросе объединения.

Дальше через «И» следуют условия на активность (нам нужны только активные записи, не активные не могут влиять на остатки) и отбор по всем измерениям, указанным в параметрах отбора виртуальной таблицы.

В секции «SELECT» происходит накопления ресурса в зависимости от вида движения («SUM(CASE WHEN T4._RecordKind = 0.0 THEN -T4._Fld22268 ELSE T4._Fld22268 END)»): Если вид движения приход («_RecordKind = 0.0»), то ресурс берется с отрицательным знаком, иначе с положительным.

То есть из таблицы движений выбираются записи с моментом времени больше или равным условию отбора по периоду виртуальной таблицы и периодом меньшим даты начала следующего месяца. При этом ресурсы накапливаются с отрицательным знаком.

При объединении запросов из результата первого (по таблице итогов) вычитается результат второго (по основной таблице) и таким образом получается остаток на нужный нам период (условие по периоду виртуальной таблицы).

Зачем все это знать…

Лично мне это помогло разобраться с избыточной блокировкой, которая не давала возможности одновременного проведения документов поступления по разным контрагентам:

При проведении документов поступления сначала анализируются остатки этого регистра, для определения был ли аванс или нет, а потом происходит запись в этот регистр.

Естественное требование к системе – возможность одновременного проведения пользователями документов по разным контрагентам или договорам. Но, если система настроена неправильно, то это требование выполняться не будет…

При выполнении запроса очень важно что бы для отбора строк запрос использовал индекс! В этом случае запрос будет выполняться быстро и блокировать для записи только те строки таблиц, используемых в запросе, которые удовлетворяют отбору…

Если запрос не использует индекс для отбора строк или использует малоселективный индекс (индекс, которому соответствует большое количество строк таблицы), то запрос будет выполняться медленно и блокировать всю (или почти всю) таблицу для записи…

Для выполнения нашего требования запрос должен использовать индекс и первые поля этого индекса должны использоваться в отборе запроса. В нашем случае, это поле - измерение ДоговорКонтрагента.

Для таблицы итогов регистра накопления платформа создает кластерный индекс с включением в него периода итогов и всех измерений в том порядке как они заданы в конфигураторе, не зависимо от того установлено ли для измерения свойство «Индексировать» или нет… Из этого следует, что если Мы переставим «ДоговорКонтрагента» в списке измерений на первое место, то получим нужный нам индекс… Кстати не используемые в отборах запросов измерения (Организация и Контрагент) лучше передвинуть в самый конец списка, тогда могут сработать такие поля индекса как «Сделка», «СчетОплаты» и «ДокументРасчетовСКонтрагентом».

Для таблицы движений регистра накопления платформа создает два индекса: кластерный индекс по периоду, в состав которого входит период, регистратор и номер строки, а также индекс по регистратору, в состав которого входит регистратор и номер строки.

Если для измерения установлено свойство «Индексировать», то платформа создаст дополнительный индекс, включив в него это измерение, период, регистратор и номер строки. Из этого следует, что установив у измерения «ДоговорКонтрагента» свойство «Индексировать», Мы получим требуемый нам индекс…

Таким образом структура регистра изменилась на следующую:

  1. ДоговорКонтрагента, типа справочник «ДоговорыКонтрагентов» (ИНДЕКСИРУЕТСЯ)
  2. Сделка, типа документ «Счет на оплату поставщику»
  3. Счет оплаты, типа ПланыСчетов.Хозрасчетный
  4. ДокументРасчетовСКонтрагентом, типа документ поступления и оплаты…
  5. Организация, типа справочник «Организации»
  6. Контрагент, типа справочник «Контрагенты»

После этого избыточные блокировки исчезли, и пользователи смогли одновременно проводить документы по разным контрагентам и договорам.

Читайте также: