Взрывной рост таблицы 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    42022    129    155    

86

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

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

3660 руб.

10.02.2017    118646    714    176    

753

Корректировка данных Программист Пользователь 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    55387    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    54052    185    29    

137

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

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

5084 руб.

07.05.2025    1561    2    0    

3

Корректировка данных Зарплата Бухгалтер 1С:Предприятие 8 1С:Зарплата и кадры бюджетного учреждения 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет НДФЛ Платные (руб)

Проверено на начало 2026 года. Обработка исправляет технические ошибки по НДФЛ, взаиморасчетам с сотрудниками в 1С:ЗУП (1С:ЗКГУ) на начало года. Фактически все ошибки, которые проявляются в ведомостях на выплату, расчетных листках, при заполнении ведомостей на выплату и отчетах 6-НДФЛ и т.д. нужно начинать исправлять с начала расчетного года. Это позволит быть уверенными, что после завершения расчетов предыдущего года, начали работать с «чистого листа» без ошибочных остатков.

61000 руб.

06.10.2023    8818    40    21    

46
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3211 28.01.26 13:18 Сейчас в теме
Из курса экспертов по техвопросам:
- И что будем делать?
... тишина ...
- Правильно, нарушать лицензионное соглашение!
2. dumsik 36 28.01.26 15:45 Сейчас в теме
А можно пояснить, что за "последним стало включение многопотока". Какой-то Ваш не типовой функционал?
3. Zlohobbit 295 28.01.26 15:50 Сейчас в теме
(2) Типовой. Многопоточка пишет в РС ДлительныеОперации. с большим количеством реквизитов, ресурсов с типом хранилище значений. Потом записи оттуда удаляются, а из BinaryData нет.
4. dumsik 36 28.01.26 16:16 Сейчас в теме
5. kalyaka 1140 28.01.26 17:05 Сейчас в теме
А есть зарегистрированная ошибка? Известно с какого релиза поправлена?
6. Zlohobbit 295 28.01.26 17:10 Сейчас в теме
(5) Да. Ошибка 60026399. На 8.3.27.1936 точно нет. Проверил лично.
7. SerVer1C 1005 28.01.26 17:11 Сейчас в теме
Писал подобную статью, как уменьшить размер таблицы SystemSettings на ~ 97%, удалив дубли, а это 3..5 % размера всей базы, но мою публикацию забрили...
pkorneenko; BigB; +2 Ответить
8. Painted 49 29.01.26 08:37 Сейчас в теме
(7) Может без дисклеймера писал? Смотри какой он здесь - большой и красивый ))
9. Zlohobbit 295 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?
11. Zlohobbit 295 29.01.26 13:53 Сейчас в теме
(10) на всякий случай уточню: вы выгрузку/загрузку выполняете через командную строку или из конфигуратора?
Скрипт под mssql можно переписать при необходимости.
12. lvv31 29.01.26 14:02 Сейчас в теме
Выгрузку/загрузку выполняем из конфигуратора;

Скрипт под mssql можно переписать - Очень интересно
Для отправки сообщения требуется регистрация/авторизация