Взрывной рост таблицы 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 хранилище значений

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

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

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

14640 руб.

29.04.2020    51280    141    162    

96

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

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

6100 руб.

10.02.2017    121798    735    177    

770

SALE! 15%

Корректировка данных Программист Пользователь 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 22814 руб.

26.08.2018    56834    19    65    

58

SALE! 15%

Файловый обмен (TXT, XML, DBF), FTP Поиск данных Инструменты администратора БД Корректировка данных Системный администратор Программист 1С:Предприятие 8 1C:Бухгалтерия 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Данная обработка позволит Вам легко и просто, а главное - быстро, выполнить сравнение данных между ЛЮБЫМИ базами (и РИБ, по правилам конвертаций) по контрольным суммам выбранных объектов баз 1С, работающих на платформах 8.3 и выше. Удобный и понятный интерфейс в виде "мастера". Высокая скорость сравнения достигается за счет специального алгоритма расчета контрольной суммы объекта/записи и сравнения по данным суммам объектов 2х баз через файл. Имеется возможность выбора реквизитов, по которым система будет сравнивать объекты. Сравнение количества записей в движениях документов, возможность сравнивать данные по правилам конвертации и не только! Выбор объектов конфигурации для КАЖДОГО узла в отдельности с индивидуальным отбором для каждого объекта конфигурации, работа с FTP, сохранение или загрузка настроек, сохранение или загрузка результата сравнения, регистрация на обмен объекта и его движений. (Обновление от 12.11.2024, версия 2.2-2.5)

24400 20740 руб.

27.10.2017    46941    32    15    

50

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

Внешняя обработка сравнивает НДФЛ из расчетного листка и НДФЛ из регистра, на разницу формирует документы в 2 шага. Исправляет расхождения, в том числе, когда Аванс больше Зарплаты

9760 руб.

01.09.2023    9012    322    93    

22

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

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

6100 руб.

28.01.2026    1496    5    0    

4
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3293 28.01.26 13:18 Сейчас в теме
Из курса экспертов по техвопросам:
- И что будем делать?
... тишина ...
- Правильно, нарушать лицензионное соглашение!
ant7498; muskul; +2 Ответить
2. dumsik 36 28.01.26 15:45 Сейчас в теме
А можно пояснить, что за "последним стало включение многопотока". Какой-то Ваш не типовой функционал?
3. Zlohobbit 309 28.01.26 15:50 Сейчас в теме
(2) Типовой. Многопоточка пишет в РС ДлительныеОперации. с большим количеством реквизитов, ресурсов с типом хранилище значений. Потом записи оттуда удаляются, а из BinaryData нет.
4. dumsik 36 28.01.26 16:16 Сейчас в теме
5. kalyaka 1182 28.01.26 17:05 Сейчас в теме
А есть зарегистрированная ошибка? Известно с какого релиза поправлена?
6. Zlohobbit 309 28.01.26 17:10 Сейчас в теме
(5) Да. Ошибка 60026399. На 8.3.27.1936 точно нет. Проверил лично.
7. SerVer1C 1104 28.01.26 17:11 Сейчас в теме
Писал подобную статью, как уменьшить размер таблицы SystemSettings на ~ 97%, удалив дубли, а это 3..5 % размера всей базы, но мою публикацию забрили...
user1827801; pkorneenko; BigB; +3 Ответить
8. Painted 49 29.01.26 08:37 Сейчас в теме
(7) Может без дисклеймера писал? Смотри какой он здесь - большой и красивый ))
9. Zlohobbit 309 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 309 29.01.26 13:53 Сейчас в теме
(10) на всякий случай уточню: вы выгрузку/загрузку выполняете через командную строку или из конфигуратора?
Скрипт под mssql можно переписать при необходимости.
14. SerVer1C 1104 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 309 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 1104 02.02.26 14:01 Сейчас в теме
(16) Но только с 23-й платформы.
А быстрее работает, потому что НЕ задействует сервер 1С, а тянет данные сразу из СУБД.
VyacheslavShilov; +1 Ответить
17. AlxPop 36 30.01.26 12:45 Сейчас в теме
"Если кому-то нужна обработка по генерации скрипта, пишите в комментарии, и я скину или добавлю к статье. "
Скиньте пожалуйста, я тож с этой фигней боролся, но так не победил...
18. Zlohobbit 309 31.01.26 14:28 Сейчас в теме
(17) у вас PGSQL или MSSQL?
19. AlxPop 36 01.02.26 21:46 Сейчас в теме
23. Zlohobbit 309 03.02.26 10:05 Сейчас в теме
(19) стучите в телегу. Скину и напишу что и в каком порядке.
30. Гость 24.04.26 23:25
(23)
скинете примеры скриптов?
21. user610020_lepestov 02.02.26 16:07 Сейчас в теме
Коллега, можете поделиться скриптами для устранения этой проблемы? Столкнулись так же на платформе 8.3.27.1719
СУБД MSSQL
22. AlxAlp 03.02.26 09:17 Сейчас в теме
Только следите, чтобы загрузка произошла в полном объеме. А то мы и такое словили.))))

Поясните данный моментик, пожалуйста)
24. Zlohobbit 309 03.02.26 10:14 Сейчас в теме
(22) объём базы при восстановлении из dt должен быть такой же как был до взрывного роста. Мы столкнулись с тем что при восстановлении база имела размер втрое меньше чем должна была быть. Проверили данные (сверкой строк в таблицах и вообще количество таблиц) и стало понятно что восстановление было не полным)))
25. AlxAlp 04.02.26 04:10 Сейчас в теме
(24) Это понятно, спасибо) Интересно, почему так вышло. Надо полагать, это ведь не только дт-шника касается, но и субд-шных бэкапов?
26. 1C_Dev_Mix 24.02.26 15:02 Сейчас в теме
Добрый день, а как связаться в ТГ, насчет обработки по генерации скрипта?
31. kernel_pan1c 08.05.26 07:26 Сейчас в теме
(26) Удалось обработку найти? или я яслепой ее не вижу?
27. HolodZar 23.04.26 05:23 Сейчас в теме
Спасибо автору! На основании вашего труда сделал скрипт для MS SQL 2008. Тоже таблица выросла до 50 гигабайт хотя реальных данных столько нет в ней. Делаем строго на копии, проверяем данные в доп. обработках, присоединенные файлы, регистр значения хранилище файлов, пробуем обновить конфигурацию - будет сообщение, что изменен тип хранения блочных данных и обновление проходит корректно. В итоге удалось высвободить 40 гигабайт данных.

-- Ищем в базе все поля с типом хранилище значения, вычисляем со смещением из него ИД с 17 по 32 байт для связи --данных с ключом "f_key" в binarydata и заполняем табилцу FinalValidKeys
-- для скорости далее не удаляем данные, а создаем копию таблицы BinaryData_New и переносим (по 10000) в неё все --сопоставленные данные между FinalValidKeys и binarydata (все связанные данные без мусора)
-- далее переименовываем таблицы BinaryData --> BinaryData_Old_Trash, BinaryData_New --> BinaryData, проверяем базу, -- данные и удаляем BinaryData_Old_Trash, делаем шринк!

USE [Имя_базы];
GO

SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

--------------------------------------------------------------------------------
-- 1. СБОР КЛЮЧЕЙ
--------------------------------------------------------------------------------
IF OBJECT_ID('tempdb..#FinalValidKeys') IS NOT NULL DROP TABLE #FinalValidKeys;
CREATE TABLE #FinalValidKeys (f_key VARBINARY(16) PRIMARY KEY);

DECLARE @TableName NVARCHAR(255), @ColumnName NVARCHAR(255), @Sql NVARCHAR(MAX);

DECLARE col_cur CURSOR FOR
SELECT t.name, c.name
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.types st ON c.user_type_id = st.user_type_id
WHERE st.name IN ('varbinary', 'binary', 'image')
AND (c.max_length >= 32 OR c.max_length = -1) -- Берем и фиксированные, и MAX поля
AND t.name <> 'binarydata'
AND t.name NOT LIKE '_Config%' AND t.name NOT LIKE '_YearOffset%';

OPEN col_cur;
FETCH NEXT FROM col_cur INTO @TableName, @ColumnName;

RAISERROR('Начинаю поиск ключей для связи с binarydata во всей базе...', 0, 1) WITH NOWAIT;

-- Берем с 33 по 64 символы из бинарных значений для формирования ИД
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Sql = '
INSERT INTO #FinalValidKeys (f_key)
SELECT DISTINCT CAST(SUBSTRING(CAST([' + @ColumnName + '] AS VARBINARY(MAX)), 17, 16) AS VARBINARY(16))
FROM [dbo].[' + @TableName + '] WITH (NOLOCK)
WHERE [' + @ColumnName + '] IS NOT NULL
AND DATALENGTH([' + @ColumnName + ']) >= 32
AND NOT EXISTS (SELECT 1 FROM #FinalValidKeys WHERE f_key = CAST(SUBSTRING(CAST([' + @ColumnName + '] AS VARBINARY(MAX)), 17, 16) AS VARBINARY(16)));';

BEGIN TRY
EXEC(@Sql);
END TRY
BEGIN CATCH

DECLARE @ErrorMsg NVARCHAR(1000) = 'ОШИБКА в таблице ' + @TableName + ', колонка ' + @ColumnName + ': ' + ERROR_MESSAGE();

-- Выводим ошибку и ПРЕРЫВАЕМ выполнение (уровень 16)
RAISERROR(@ErrorMsg, 16, 1);

-- На всякий случай закрываем курсор перед выходом
CLOSE col_cur;
DEALLOCATE col_cur;
RETURN;

END CATCH

FETCH NEXT FROM col_cur INTO @TableName, @ColumnName;
END

CLOSE col_cur;
DEALLOCATE col_cur;

DECLARE @KeysCount INT;
SELECT @KeysCount = COUNT(*) FROM #FinalValidKeys;
RAISERROR('Поиск завершен. Найдено уникальных ключей: %d', 0, 1, @KeysCount) WITH NOWAIT;

--------------------------------------------------------------------------------
-- 2. ПОДГОТОВКА НОВОЙ ТАБЛИЦЫ
--------------------------------------------------------------------------------
IF OBJECT_ID('dbo.BinaryData_New') IS NOT NULL DROP TABLE dbo.BinaryData_New;

-- Копируем структуру
SELECT TOP 0 * INTO dbo.BinaryData_New FROM dbo.BinaryData;

-- Создаем индексы как в оригинале (по твоим данным)
CREATE UNIQUE NONCLUSTERED INDEX [BinaryDataInd_New] ON [dbo].[BinaryData_New] ([f_key] ASC, [f_off] ASC)
WITH (ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [BinaryDataInd2_New] ON [dbo].[BinaryData_New] ([f_num] ASC)
WITH (ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY];

--------------------------------------------------------------------------------
-- 3. ЦИКЛИЧЕСКИЙ ПЕРЕНОС
--------------------------------------------------------------------------------
DECLARE @BatchSize INT = 10000;
DECLARE @RowsInserted INT = 1;
DECLARE @TotalInserted INT = 0;

RAISERROR('Начинаю перенос данных в BinaryData_New...', 0, 1) WITH NOWAIT;

WHILE @RowsInserted > 0
BEGIN
INSERT INTO dbo.BinaryData_New ([f_key], [f_off], [f_num], [f_data])
SELECT TOP (@BatchSize)
orig.[f_key], orig.[f_off], orig.[f_num], orig.[f_data]
FROM dbo.BinaryData AS orig WITH (NOLOCK)
WHERE orig.f_key IN (SELECT f_key FROM #FinalValidKeys)
AND NOT EXISTS (
SELECT 1 FROM dbo.BinaryData_New AS copy WITH (NOLOCK)
WHERE copy.f_key = orig.f_key
AND copy.f_off = orig.f_off
);

SET @RowsInserted = @@ROWCOUNT;
SET @TotalInserted = @TotalInserted + @RowsInserted;

IF @RowsInserted > 0
BEGIN

DECLARE @TimeString VARCHAR(8) = CONVERT(VARCHAR, GETDATE(), 108);


RAISERROR('%s: Перенесено строк: %d', 0, 1, @TimeString, @TotalInserted) WITH NOWAIT;
END

WAITFOR DELAY '00:00:00.200'; -- Пауза для стабильности
END

--------------------------------------------------------------------------------
-- 4. ФИНАЛЬНАЯ ПРОВЕРКА
--------------------------------------------------------------------------------
DECLARE @ExpectedCount INT;
-- Считаем, сколько уникальных f_key из нашего списка ДЕЙСТВИТЕЛЬНО есть в старой таблице
SELECT @ExpectedCount = COUNT(DISTINCT f_key)
FROM dbo.BinaryData WITH (NOLOCK)
WHERE f_key IN (SELECT f_key FROM #FinalValidKeys);

DECLARE @ActualCount INT;
-- Считаем, сколько уникальных f_key реально переехало
SELECT @ActualCount = COUNT(DISTINCT f_key) FROM dbo.BinaryData_New WITH (NOLOCK);

PRINT '----------------------------------------------------------';
PRINT 'РЕЗУЛЬТАТЫ ПЕРЕНОСА:';
PRINT 'Найдено всего записей в базе: ' + CAST(@KeysCount AS VARCHAR);
PRINT 'Из них физически было в BinaryData: ' + CAST(@ExpectedCount AS VARCHAR);
PRINT 'Успешно перенесено в BinaryData_New: ' + CAST(@ActualCount AS VARCHAR);

IF @ActualCount >= @ExpectedCount
BEGIN
PRINT 'СТАТУС: УСПЕХ! Все данные перенесены.';
PRINT '----------------------------------------------------------';
PRINT 'Финальные шаги:';
PRINT '1. EXEC sp_rename ''dbo.BinaryData'', ''BinaryData_Old_Trash'';';
PRINT '2. EXEC sp_rename ''dbo.BinaryData_New'', ''BinaryData'';';
PRINT '3. DROP TABLE dbo.BinaryData_Old_Trash; -- Удаление мусора';
PRINT '4. DBCC SHRINKFILE(Имя файла базы данных, 10); ';
END
ELSE
BEGIN
RAISERROR('ВНИМАНИЕ: В новой таблице меньше записей, чем в источнике.', 16, 1);
END
zotovkv; Zlohobbit; y22-k; +3 Ответить
28. HolodZar 23.04.26 08:01 Сейчас в теме
Все обмены, которые могут вносить изменения в binarydata в момент переноса/переименования желательно остановить. В комментарии выше опечатка: регистр значений - сведений конечно.
29. tystik 10 24.04.26 16:34 Сейчас в теме
МММ, а что еще, кроме реквизитов с типом ХранилищеЗначения, могло лежать в binarydata, что вариант №1 из скрипта привел к разрушению базы?


Или ошибка была связана с тем что в платформе есть путаница с именами таблиц расширений (x1 постфикс)?

Пишем подобный скрипт у себя, и взяли все реквизиты с типом хранилище значений, и всё, что не нашли из этого списка, дропнули....
Для отправки сообщения требуется регистрация/авторизация