Взрывной рост таблицы binarydata при отказе от совместимости на платформе 8.3.27 ранних версий

28.01.26

Задачи пользователя - Корректировка данных

Публикация размещена исключительно в образовательных целях и подходит только для платформы версии 8.3.27.
Использует недокументированные средства доступа к базе данных 1С. Прямое обращение к СУБД нарушает лицензионное соглашение,
может изменить поведение платформы, привести к разрушению базы данных, скомпрометировать данные,
а также привести к отказу в официальной поддержке Фирмы 1С.
В эти новогодние праздники словили взрывной рост нашей 1С УХи! Что стало причиной? Цепочка действий! Первым звеном стал переход на платформу 8.3.27.1688. Но сам по себе он никаких проблем не вызвал. Да и было это еще в ноябре. Вторым звеном стало обновление до последнего вендорского релиза (он нужна для использования НДС 22%). Она содержала такое изменение, как отказ от совместимости (ранее была совместимость с 8.3.24). А последним стало включение многопотока. И вот мы имеем БД 1,4 ТБт вместо 600 ГБт причем всего за 4 дня. После того как проблема стала очевидна, мы в авральном режиме перешли на новую версию платформы 8.3.27.1936. Это действие остановило взрывной рост., но уменьшения не случилось. Самый простой и правильный вариант, именно это рекомендует фирма 1С, произвести выгрузку/загрузку dt. Но это долго и скучно и не всегда возможно при больших размерах БД и маленьких технологических окнах. Кроме того: Всегда должен быть план Б!

И поэтому для таких пытливых любителей найти приключения на пятую точку и предлагаю вариант со скриптами. Ну что погнали!

Первое, что я сделал, это перебрал все реквизиты всех объектов БД с типом "Хранилище значений" и, узнав их абсолютные имена в терминах БД (в нашем случае это PGSQL), получил скрипт типа:   
 


-- Удаляем временную таблицу, если она существует
DROP TABLE IF EXISTS temp_bytea_ids;
-- Создаем временную таблицу с уникальными bytea ID
CREATE TEMP TABLE temp_bytea_ids (
    id_MD5 TEXT PRIMARY KEY, -- MD5 в текстовом виде (32 символа)
    id TEXT  --ID в текстовом виде (128 символа)
);
-- Заполняем времянку данными из всех таблиц с не пустым реквизитом типа ХЗ
INSERT INTO temp_bytea_ids (id_MD5, id) 
SELECT
    MD5(temp_ids.id) as id_MD5,    
    temp_ids.id as id
    
FROM (

SELECT  
	SUBSTRING(encode(_Fld3315, 'hex') FROM 33 FOR 32) as id_32, encode(_Fld3315, 'hex') as id 
FROM public._Reference85 WHERE _Fld3315 IS NOT NULL AND octet_length(_Fld3315) > 0
UNION
SELECT  
	SUBSTRING(encode(_Fld3312, 'hex') FROM 33 FOR 32) as id_32, encode(_Fld3312, 'hex') as id 
FROM public._Reference85 WHERE _Fld3312 IS NOT NULL AND octet_length(_Fld3312) > 0
UNION
.....
.....
.....
.....
SELECT  
	SUBSTRING(encode(_Fld8069, 'hex') FROM 33 FOR 32) as id_32, encode(_Fld8069, 'hex') as id 
FROM public._Reference303_VT8065 WHERE _Fld8069 IS NOT NULL AND octet_length(_Fld8069) > 0

) as temp_ids;
;

-- Поиск префикса 
SELECT 
	sum(1) as summa,
	left(temp_id.id, 32)
FROM
	temp_bytea_ids as temp_id 
where
	LENGTH(id) = 128
group by 
	left(temp_id.id, 32)
having 
	sum(1) > 1			

Выполнив этот скрипт, мы получим от одного до N префиксов ID, которые используются при перемещении данных в binarydata. Изначально сразу после этого я удалял все, что не нашлось этим запросом. Но по итогу БД больше не открывалась. Это мне намекнуло, что найдены не все ID.

Я выяснил, что на стороне таблицы, ранее хранивший бинарные данные, теперь лежит ID, имеющий длину 128 символов:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - префикс 32 символа

YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY - ID, именно он хранится в качестве идентификатора в binarydata
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ - не анализировал.

Так что, зная длину 128 символов и префиксы, можно поискать со стороны БД. Выполним еще один скрипт. Он нужен для того что бы найти все ID используемые в БД (не важно хранилище значений там или нет). Все бинарные данные, превышающие минимальный размер хранимый "на месте" (в самой таблице владелице) в 8.3.27 переносятся в binarydata.

ИИ мне сказал, что вот так можно оббежать все таблицы БД и все их колонки с типом bytea и если там есть строка 128 символов и префикс равен найденным ранее, то мы нашли то, что нужно, а именно абсолютное имя таблицы и имя поля, где хранится ID из binarydata
 

DO $$
DECLARE
    schema_name TEXT;
    table_name TEXT;
    column_name TEXT;
    sql_query TEXT;
    cnt INTEGER;
    result_text TEXT := '';
    prefix1 TEXT := '11111111111111111111111111111111';
    prefix2 TEXT := '22222222222222222222222222222222';
BEGIN
    FOR schema_name, table_name, column_name IN 
        SELECT 
            t.table_schema,
            t.table_name,
            c.column_name
        FROM 
            information_schema.tables t
            JOIN information_schema.columns c 
                ON t.table_schema = c.table_schema 
                AND t.table_name = c.table_name
        WHERE 
            t.table_type = 'BASE TABLE'
            AND t.table_schema NOT IN ('pg_catalog', 'information_schema')
            AND c.data_type = 'bytea'
            AND t.table_schema = 'public'  -- Только схема public
        ORDER BY 
            t.table_schema,
            t.table_name,
            c.column_name
    LOOP
        -- Проверяем, есть ли в этой колонке строки с нужными условиями
        -- Используем OR для проверки двух префиксов
        sql_query := FORMAT(
            'SELECT COUNT(*) FROM %I.%I ' ||
            'WHERE %I IS NOT NULL ' ||
            'AND octet_length(%I) > 0 ' ||
            'AND LENGTH(encode(%I, ''hex'')) = 128 ' ||
            'AND (LEFT(encode(%I, ''hex''), 32) = %L ' ||
            '     OR LEFT(encode(%I, ''hex''), 32) = %L)',
            schema_name,
            table_name,
            column_name,
            column_name,
            column_name,
            column_name, prefix1,
            column_name, prefix2
        );
        
        BEGIN
            EXECUTE sql_query INTO cnt;
            
            IF cnt > 0 THEN
                result_text := result_text || 
                    FORMAT('Схема: %s, Таблица: %s, Колонка: %s, Найдено строк: %s' || E'\n',
                          schema_name,
                          table_name,
                          column_name,
                          cnt);
            END IF;
        EXCEPTION
            WHEN OTHERS THEN
                -- Пропускаем ошибки (например, если нет прав на таблицу)
                CONTINUE;
        END;
    END LOOP;
    
    -- Выводим результат
    IF result_text = '' THEN
        RAISE NOTICE 'Колонки с указанными условиями не найдены';
    ELSE
        RAISE NOTICE 'Найдены колонки:%', E'\n' || result_text;
    END IF;
END $$;

 

Скрипт выше написан для нашего proda там было использовано два префикса.

Теперь дело за малым, зная все пары таблица + поле нашей БД, где хранится ID из binarydata, можно найти все используемые ID. И тогда все, что есть в binarydata, но не имеют пары, и есть лишние.)))

-- Удаляем временную таблицу, если она существует
DROP TABLE IF EXISTS temp_bytea_ids;
-- Создаем временную таблицу с уникальными bytea ID
CREATE TEMP TABLE temp_bytea_ids (
    id_32 TEXT, -- ID в текстовом виде первые 32 символа (32 символа)
    id_MD5 TEXT PRIMARY KEY -- MD5 в текстовом виде (32 символа)
);
-- Заполняем времянку данными из всех таблиц с реквизитом типа ХЗ
INSERT INTO temp_bytea_ids (id_32, id_MD5) 
SELECT
    temp_ids.id_32 as id_32
    MD5(temp_ids.id) as id_MD5
    
FROM (

SELECT  
	SUBSTRING(encode(_fld80282, 'hex') FROM 33 FOR 32) as id_32, encode(_fld80282, 'hex') as id 
FROM public._reference79206 WHERE _fld80282 IS NOT NULL AND octet_length(_fld80282) > 0
UNION
SELECT  
	SUBSTRING(encode(_fld75303, 'hex') FROM 33 FOR 32) as id_32, encode(_fld75303, 'hex') as id 
FROM public._reference75088x1 WHERE _fld75303 IS NOT NULL AND octet_length(_fld75303) > 0
UNION
.....
.....
.....
.....
SELECT  
	SUBSTRING(encode(_fld75199, 'hex') FROM 33 FOR 32) as id_32, encode(_fld75199, 'hex') as id 
FROM public._reference75082x1 WHERE _fld75199 IS NOT NULL AND octet_length(_fld75199) > 0

) as test;
-- Индекс для id_32 колонки
CREATE INDEX ON temp_bytea_ids(id_32);

-- Удаление записей из public.binarydata которых нет в temp_bytea_ids порциями по 1000
DO $$
DECLARE
    rows_deleted INTEGER;
    total_deleted INTEGER := 0;
    batch_size INTEGER := 1000;
    row_ids_to_delete TEXT[];
BEGIN
    LOOP
        -- 1. Сначала получаем ID для удаления (максимум batch_size)
        SELECT array_agg(encode(bd.f_key, 'hex')) 
        INTO row_ids_to_delete
        FROM public.binarydata bd
        WHERE NOT EXISTS (
            SELECT 1 FROM temp_bytea_ids tbi 
            WHERE tbi.id_32 = encode(bd.f_key, 'hex')
        )
        AND bd.f_key IS NOT NULL
        LIMIT batch_size;
        
        -- 2. Если массив пустой, выходим из цикла
        EXIT WHEN row_ids_to_delete IS NULL;
        
        -- 3. Удаляем записи по найденным ID
        DELETE FROM public.binarydata bd
        WHERE encode(bd.f_key, 'hex') = ANY(row_ids_to_delete);
        
        -- 4. Получаем количество удаленных строк
        GET DIAGNOSTICS rows_deleted = ROW_COUNT;
        total_deleted := total_deleted + rows_deleted;
        
        -- 5. Выводим информацию о прогрессе
        RAISE NOTICE 'Удалено % записей, всего удалено: %', rows_deleted, total_deleted;
        
        -- 6. Если удалено меньше batch_size, значит это последняя порция
        EXIT WHEN rows_deleted < batch_size;
        
        -- 7. Небольшая пауза для уменьшения нагрузки на БД
        PERFORM pg_sleep(0.01);
    END LOOP;
    
    RAISE NOTICE 'Удаление завершено. Всего удалено записей: %', total_deleted;
END $$;

-- Проверка оставшихся записей (опционально)
SELECT COUNT(*) as remaining_rows 
FROM public.binarydata bd
WHERE NOT EXISTS (
    SELECT 1 FROM temp_bytea_ids tbi 
    WHERE tbi.id_32 = encode(bd.f_key, 'hex')
);

Запускаем скрипт, удаляем все лишнее и снова наслаждаемся своей небольшой БД.

Но опять же повторюсь: это лишь рассуждения на тему и я никого не призываю действовать по написанному Выше! Самый простой и верный способ по прежнему выгрузка/загрузка в dt. Только следите, чтобы загрузка произошла в полном объеме. А то мы и такое словили.))))   

Если кому-то нужна обработка по генерации скрипта, пишите в комментарии, и я скину или добавлю к статье. 

Вступайте в нашу телеграмм-группу Инфостарт

binarydata взрывной рост 8.3.27 хранилище значений

См. также

Закрытие периода Инструменты администратора БД Корректировка данных Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Расширение «Оперативное проведение» в 4 раза уменьшает время проведения документов и закрытия месяца. Является комплексным решением проблем 62 и 60 счетов. Оптимизирует проведение при включенной функциональной опции «Раздельный учет НДС». Используется в более 10 организациях уже 2 года. Совместимо с конфигурацией Бухгалтерия 3.0 (+КОРП).

14640 руб.

29.04.2020    42450    129    158    

87

Корректировка данных Системный администратор Программист 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Незаменимая обработка для сопровождения конфигураций: ERP, УТ, КА. Позволяет вычистить многие ошибки в ключах аналитики, в ключевых справочниках конфигурации.

3660 руб.

10.02.2017    118899    717    177    

756

Корректировка данных Программист Пользователь 1С:Предприятие 8 1С:Управление торговлей 10 1С:Розница 2 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Представьте, что есть система QR - кодирования, которая НЕ ТРЕБУЕТ изменения конфигурации, НЕ ТРЕБУЕТ изменения ни одной печатной формы для добавления QR-кода, включая внешние, НЕ ХРАНИТ данные штрихкодов и их связь, от чего база не "пухнет", ИМЕЕТ возможность закодировать в QR-коде произвольные данные параметров для последующей обработки полученных данных, УМЕЕТ прикреплять сканы, УМЕЕТ обработать считанный QR-код как ВЫ захотите. А также ХРАНИТ историю операций в обход базы для каждого пользователя в отдельности и УМЕЕТ работать с 2D - сканерами. А также автоматически распознавать отсканированные печатные формы (картинки или pdf-файлы) и выполнять заданные произвольные алгоритмы, в том числе прикрепление их к документам! Обновление 3.3 от 24.06.2025!

26840 руб.

26.08.2018    55512    18    65    

57

Закрытие периода Корректировка данных Программист Пользователь 1С:Предприятие 8 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Внешняя обработка, позволяющая произвольным образом заполнять документ "Корректировка регистров" Предназначена для использования в конфигурациях "Управление торговлей 11", "Управление небольшой фирмой", "ERP Управление предприятием", а также в других конфигурациях, в состав которых входит библиотека стандартных подсистем (БСП) версии 2.2+ и указанный выше документ.

5084 руб.

13.07.2015    54128    186    31    

138

Корректировка данных Закрытие периода Мастера заполнения Программист Бизнес-аналитик Бухгалтер Пользователь 1С 8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление нашей фирмой 3.0 1С:УНФ Платные (руб)

Оптимизируйте процесс закрытия периодов. Автоматизируйте любые, даже самые сложные правила переноса и выполните инвентаризацию остатков за минуты. Гибкая обработка для 1С, которая работает как самостоятельный модуль — без привязки к БСП и с поддержкой большинства конфигураций. Ваш идеальный помощник для закрытия периода, исправления ошибок, реорганизации учета, корректировки и списания остатков.

6100 руб.

28.01.2026    351    2    0    

2

Ценообразование, анализ цен Корректировка данных 1С:Предприятие 8 1С:Управление торговлей 11 Платные (руб)

Подключаемая внешняя обработка с простой настройкой - позволяет автоматически рассчитывать в документах продажи скидку процентом на каждый второй, третий и т.д. товар с наименьшей ценой из выбранного сегмента. Ничего лишнего для удобного использования!

5084 руб.

07.05.2025    1602    2    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3211 28.01.26 13:18 Сейчас в теме
Из курса экспертов по техвопросам:
- И что будем делать?
... тишина ...
- Правильно, нарушать лицензионное соглашение!
ant7498; muskul; +2 Ответить
2. dumsik 36 28.01.26 15:45 Сейчас в теме
А можно пояснить, что за "последним стало включение многопотока". Какой-то Ваш не типовой функционал?
3. Zlohobbit 305 28.01.26 15:50 Сейчас в теме
(2) Типовой. Многопоточка пишет в РС ДлительныеОперации. с большим количеством реквизитов, ресурсов с типом хранилище значений. Потом записи оттуда удаляются, а из BinaryData нет.
4. dumsik 36 28.01.26 16:16 Сейчас в теме
5. kalyaka 1144 28.01.26 17:05 Сейчас в теме
А есть зарегистрированная ошибка? Известно с какого релиза поправлена?
6. Zlohobbit 305 28.01.26 17:10 Сейчас в теме
(5) Да. Ошибка 60026399. На 8.3.27.1936 точно нет. Проверил лично.
7. SerVer1C 1007 28.01.26 17:11 Сейчас в теме
Писал подобную статью, как уменьшить размер таблицы SystemSettings на ~ 97%, удалив дубли, а это 3..5 % размера всей базы, но мою публикацию забрили...
user1827801; pkorneenko; BigB; +3 Ответить
8. Painted 49 29.01.26 08:37 Сейчас в теме
(7) Может без дисклеймера писал? Смотри какой он здесь - большой и красивый ))
9. Zlohobbit 305 29.01.26 08:44 Сейчас в теме
(8) Дисклеймер установили модераторы. Но я не против, раз это даёт возможность опубликовать статью. Ну и очевидно что если у вас отработает выгрузка/загрузка dt то использовать нужно ее! Тем более что это помогает поверил лично, на платформе где ошибка устранена.
10. lvv31 29.01.26 13:47 Сейчас в теме
Добрый День! Аналогичная проблема 1С ERP УХ
Перешли в Новогодние праздники на ранний 27 релиз платформы 8.3.27.1786.
Увидели, что раздувается binarydata в СУБД (у нас MS SQL)

Платформу обновили до 8.3.27.1964, вроде binarydata стала ходить вокруг своих 4,4Тб

Выгружали в dt но постоянно выпадает ошибка:

Ошибка обращения к серверу 1С: Предприятия.
по причине:
Соединение с сервером баз данных разорвано администратором
Microsoft SQL Server Native Client 11.0: Named Pipes Provider: Could not open a connection to SQL Server [2].
HRESULT=8004005. HRESULT=80004005, HRESULT=80004005, SQLSrvr: SQLSTATE=08001, state=1, Serverity=10, native=2, line=0

Подробно изучил Вашу статью, хотел бы углубиться в вопрос;
Так как у нас MS SQL, нам блок переделывать обработки на PG SQL переделывать на MS SQL

+ Вопрос: выгрузка в dt возможна, если лог sql data 4.9Tb и лог 0,117Tb?
user1827801; +1 Ответить
11. Zlohobbit 305 29.01.26 13:53 Сейчас в теме
(10) на всякий случай уточню: вы выгрузку/загрузку выполняете через командную строку или из конфигуратора?
Скрипт под mssql можно переписать при необходимости.
14. SerVer1C 1007 29.01.26 16:02 Сейчас в теме
(10)
+ Вопрос: выгрузка в dt возможна, если лог sql data 4.9Tb и лог 0,117Tb?

Выгрузить в DT-файл можно базу любого размера, главное, чтобы у вас было под него место на диске Ц: (ну или где у вас там система), причём, это не зависит от конечного пути выгружаемого файла, т.к. буферизироваться он будет именно на системном диске!

Пока писал коммент, появилась идея: если на Ц нет места, можно вынести папку, в которую временно сохраняется DT, на другой диск через механизм ссылок. Пока не проверял, но нет оснований сомневаться в работоспособности такого подхода.
_Raiden_; VyacheslavShilov; +2 Ответить
15. _Raiden_ 30.01.26 09:56 Сейчас в теме
(10) Увеличте значения в настройках кластера 1С чтобы процесс не прерывался:
"Проблемные процессы завершать через"
"Интервал превышения допустимого объёма памяти"
12. lvv31 29.01.26 14:02 Сейчас в теме
Выгрузку/загрузку выполняем из конфигуратора;

Скрипт под mssql можно переписать - Очень интересно
13. triviumfan 102 29.01.26 15:06 Сейчас в теме
(12) попробуй сделать выгрузку в консоли (наверное, через ibcmd стабильнее). Хотя, я всё равно не верю, что что-либо не зависнет, особенно, при загрузке).
16. Zlohobbit 305 30.01.26 10:20 Сейчас в теме
(12) 1С рекомендует выполнять выгрузку/загрузку больших БД через командную строку. Потому что так работает стабильнее.
undefined

"C:\Program Files\1cv8\8.3.25.1394\bin\ibcmd.exe" infobase dump --db-server=127.0.0.1 --dbms=MSSQLServer --db-user=sa --db-pwd=ПАРОЛЬ_ОТ_Сервера_SQL --db-name=bakirovunf --data="d:\BD_1C\Backup1C\Удалить" "d:\BD_1C\Backup1C\bakirov_unf8.10.2024.dt"
Объяснение команды:
mitok.ru
C:\Program Files\1cv8\8.3.25.1394\bin\ibcmd.exe — путь к исполняемому файлу утилиты.
infobase dump — команда для выгрузки базы данных.
--db-server=127.0.0.1 — адрес сервера баз данных (в данном случае — локальный сервер).
--dbms=MSSQLServer — тип СУБД, используемой для базы данных (Microsoft SQL Server).
--db-user=sa — пользователь базы данных с правами на выгрузку.
--db-pwd=ПАРОЛЬ_ОТ_Сервера_SQL — пароль от учётной записи.
--db-name=bakirovunf — название базы данных, которую необходимо выгрузить.
--data=“d:\BD_1C\Backup1C\Удалить” — временная папка для хранения промежуточных данных выгрузки.
"d:\BD_1C\Backup1C\bakirov_unf8.10.2024.dt" — полный путь и имя файла, в который будет выполнена выгрузка базы.

https://its.1c.ru/db/v8327doc#bookmark:adm:TI000001158 - вот коротенько на итс есть инфа
20. SerVer1C 1007 02.02.26 14:01 Сейчас в теме
(16) Но только с 23-й платформы.
А быстрее работает, потому что НЕ задействует сервер 1С, а тянет данные сразу из СУБД.
VyacheslavShilov; +1 Ответить
17. AlxPop 28 30.01.26 12:45 Сейчас в теме
"Если кому-то нужна обработка по генерации скрипта, пишите в комментарии, и я скину или добавлю к статье. "
Скиньте пожалуйста, я тож с этой фигней боролся, но так не победил...
18. Zlohobbit 305 31.01.26 14:28 Сейчас в теме
(17) у вас PGSQL или MSSQL?
19. AlxPop 28 01.02.26 21:46 Сейчас в теме
23. Zlohobbit 305 03.02.26 10:05 Сейчас в теме
(19) стучите в телегу. Скину и напишу что и в каком порядке.
21. user610020_lepestov 02.02.26 16:07 Сейчас в теме
Коллега, можете поделиться скриптами для устранения этой проблемы? Столкнулись так же на платформе 8.3.27.1719
СУБД MSSQL
22. AlxAlp 03.02.26 09:17 Сейчас в теме
Только следите, чтобы загрузка произошла в полном объеме. А то мы и такое словили.))))

Поясните данный моментик, пожалуйста)
24. Zlohobbit 305 03.02.26 10:14 Сейчас в теме
(22) объём базы при восстановлении из dt должен быть такой же как был до взрывного роста. Мы столкнулись с тем что при восстановлении база имела размер втрое меньше чем должна была быть. Проверили данные (сверкой строк в таблицах и вообще количество таблиц) и стало понятно что восстановление было не полным)))
25. AlxAlp 04.02.26 04:10 Сейчас в теме
(24) Это понятно, спасибо) Интересно, почему так вышло. Надо полагать, это ведь не только дт-шника касается, но и субд-шных бэкапов?
Для отправки сообщения требуется регистрация/авторизация