Знакомая картина: запускаете обработку, которая показывает, из чего состоит база. Наверху списка стоит таблица на 244 ГБ. Вы идёте её чистить, договариваетесь на окно, сворачиваете, удаляете, переиндексируете. База после этого худеет на 19 ГБ.
Так вышло у меня. Разница между тем, что показала оценка, и тем, что лежало на диске, оказалась не в процентах, а в разы. Ниже замер на живой базе: где именно оценка по метаданным врёт, насколько, и что из этого следует для любого инструмента, который считает размер таким способом.
Замер бьёт по моей же опубликованной обработке. Поэтому сперва цифры, потом выводы.
Что и на чём мерили
База: недельная копия УПП заказчика, 3 446,7 ГБ файлов данных. Не синтетика и не демо, а рабочая конфигурация с историей.
Факт брался из СУБД:
SELECT o.name, SUM(ps.used_page_count) * 8 / 1024.0 AS mb FROM sys.dm_db_partition_stats ps JOIN sys.objects o ON o.object_id = ps.object_id GROUP BY o.name
Оценка считалась побайтно по метаданным: тип реквизита, объявленная длина, число записей. Тот же алгоритм, что живёт в опубликованной Карте объёмов базы 1С и ещё в паре инструментов, которые ходят по конфигурации без доступа к СУБД.
Сопоставимых строк вышло 932. Дальше два списка сравнивались как рейтинги: совпадает ли верхушка.
Главное число: топ-5 не совпал ни разу
| Что сверяли | Совпало |
|---|---|
| топ-5 по факту против топ-5 по оценке | 0 из 5 |
| топ-10 | 3 из 10 |
| топ-20 | 10 из 20 |
| топ-100 | 81 из 100 |

Обратите внимание на форму кривой. По всему массиву корреляция Спирмена 0,907, и такое число в отчёте выглядит как знак качества. Но внутри топ-50 по факту она падает до 0,484. Высокая общая корреляция набирается на хвосте: мелкие таблицы оценка расставляет прилично, а именно там, где вы ищете виновника, порядок рассыпается.
Это первое, что стоит запомнить: агрегатная точность инструмента и точность в верхушке списка - разные вещи. Верхушка это и есть весь смысл такого отчёта, а меряют обычно среднее.
Разброс по отдельным строкам: медиана отношения факт к оценке 1,15 при p10 = 0,25 и p90 = 2,07. То есть у каждой десятой строки промах вчетверо в одну сторону и у каждой десятой вдвое в другую.
Причём разброс систематический, а не случайный:
| Ширина таблицы | Медиана факт/оценка | Что это значит |
|---|---|---|
| до 100 байт | 1,58 | оценка занижает |
| шире 3 200 байт | 0,13 | оценка завышает в разы |
Причина простая и лечению не поддаётся: строковый реквизит считается по объявленной длине, а лежит по факту заполнения. Объявили 500 символов, пишете туда в среднем 12 - оценка посчитает 500. Чем шире таблица по объявленным типам, тем сильнее она раздувается в оценке.
Напрашивается калибровка: раз промах систематичен по ширине, добавим поправочный коэффициент. Я попробовал. Топ-10 вырос с 3 совпадений до 4. На этом всё: калибровка чинит среднее и не чинит порядок, потому что заполненность строк у разных таблиц разная и по ширине не выводится.
Три дыры, которые оценка не видит вообще
Промах по строковым реквизитам это ещё не самое интересное. Хуже то, чего в оценке нет как класса.
1. Служебные таблицы регистров
Итоги, субконто, журналы документов. Их нет в дереве метаданных как отдельных объектов, поэтому обработка, которая обходит конфигурацию, их просто не видит.
На замеряемой базе это 225 таблиц, 582,1 ГБ данных и 533,9 ГБ индексов. Больше терабайта вне карты.
Отсюда самый показательный промах: регистр бухгалтерии по факту весит 448 ГБ, а оценка даёт 30,7 ГБ. Недооценка в 14,6 раза, и не потому, что плохо посчитали записи, а потому что основной вес лежит в таблицах итогов, о которых оценка не подозревает.
2. Хранилища значения и неограниченные строки
LOB-данные на той же базе: 234,2 ГБ.
Чемпион вранья живёт здесь: регистр сведений на 18 тысяч записей физически занимает 46 ГБ при оценке 0,06 ГБ. Промах в 745 раз. В списке обработки он стоит на 358-м месте, то есть человек до него не долистает никогда.
Логика оценки тут бессильна принципиально: у хранилища значения нет объявленного размера. Туда кладут и пустую структуру, и присоединённый файл на 40 мегабайт, и в метаданных это одинаковый реквизит.
3. Индексы
Индексы не считает никто, а весят они сопоставимо с данными: плюс 61 % к данным по строкам карты и плюс 71 % по всей выборке. По отдельным таблицам доходило до плюс 645 %.
Для разговора "почему база 3,4 ТБ" это половина ответа, которой в отчёте нет.
Разброс тут тоже неслучайный. Плюс 645 % набирают не какие попало таблицы, а регистры сведений и накопления с длинным набором измерений: платформа строит по ним несколько составных индексов, каждый из которых тащит в себе ключи всех измерений плюс ссылку на регистратор. У таблицы с восемью измерениями индексная часть спокойно перевешивает данные в несколько раз, и с точки зрения диска это такое же место, как записи.
Практическое следствие неприятное: таблица, которую оценка считает средней, может стоить дороже всех именно индексами. И наоборот, документ с широкой табличной частью и одним индексом по ссылке в отчёте выглядит тяжелее, чем есть.
Отсюда же берётся частый спор про "почистили половину записей, а файл не уменьшился". Записи ушли, страницы освободились внутри файла, но сам файл остался прежнего размера, а индексы после массового удаления ещё и фрагментировались. Оценка по метаданным про это не знает ничего: она считает описание, а не то, как данные легли на страницы.
Промах в другую сторону, и он опаснее
Всё перечисленное занижает. Но есть и обратный случай, и именно он приводит к бесполезному окну обслуживания.
Табличная часть "Контакты" одного из документов: 207 млн записей. Обработка ставит её на первое место с оценкой 244 ГБ. Физически там 19 ГБ.
Механика та же: много записей, широкие строковые реквизиты по объявленной длине, реальная заполненность копеечная. Но результат хуже, чем недооценка: человек видит первую строку списка, считает её ответом и идёт тратить выходные на чистку таблицы, которая не решает проблему.
Недооценка прячет виновника. Переоценка подсовывает ложного. Второе дороже, потому что ведёт к действию.
Почему это не лечится "доработкой алгоритма"
Соблазн после такого замера один: улучшить формулу. Учесть среднюю заполненность, добавить коэффициенты по типам, прикинуть индексы.
Не работает, и вот почему. Оценка по метаданным отвечает на вопрос "сколько эта таблица могла бы весить при таком описании". Факт отвечает на вопрос "сколько она весит". Между ними лежит заполненность конкретной базы, а она:
- не выводится из метаданных ни в каком виде;
- отличается у двух баз одной конфигурации в разы;
- меняется со временем в одной и той же базе.
То есть это не погрешность, которую можно уменьшить, а другая величина, которую мы выдаём за искомую.
Здесь стоит сказать прямо, потому что это касается и моей публикации тоже: инструмент на оценке по метаданным может честно сказать "эта таблица большая", но не может сказать "эта таблица самая большая". И тем более не может сказать "вот из-за неё встанет база". Первую строку такого списка читать как ответ нельзя.
Что делать практически
Есть доступ к СУБД - берите факт, а не оценку. Это один запрос, и он не требует ни прав sysadmin, ни остановки базы:
SELECT o.name AS table_name, SUM(CASE WHEN ps.index_id < 2 THEN ps.used_page_count ELSE 0 END) * 8 / 1024.0 AS data_mb, SUM(CASE WHEN ps.index_id >= 2 THEN ps.used_page_count ELSE 0 END) * 8 / 1024.0 AS index_mb, SUM(ps.row_count) AS rows_cnt FROM sys.dm_db_partition_stats ps JOIN sys.objects o ON o.object_id = ps.object_id AND o.type = 'U' GROUP BY o.name ORDER BY 2 DESC
Дальше остаётся сопоставить служебные имена таблиц с объектами конфигурации. Платформа отдаёт эту карту сама:
Соответствие = ПолучитьСтруктуруХраненияБазыДанных(, Истина);
Второй параметр как раз включает служебные таблицы, и в выборке появляются те самые итоги и субконто, которых нет в дереве метаданных.
Нет доступа к СУБД - меняйте формулировку результата. Оценка годится как список кандидатов, а не как рейтинг. Практически это значит:
- не называть первую строку виновником, а говорить "проверьте эти тридцать";
- писать рядом с числом, что это верхняя граница по объявленным типам, а не измеренный размер;
- отдельно предупреждать, что регистры бухгалтерии и накопления недооценены систематически, потому что их служебные таблицы в оценку не входят;
- не показывать места в списке как результат: место создаёт ложную уверенность там, где её нет.
Проверяемый ориентир из замера: топ-30 по оценке почти наверняка содержит настоящий топ-10 (в моём случае 81 из 100 в топ-100 и 10 из 20 в топ-20). То есть кандидатов оценка отбирает, а порядок между ними не определяет.
Отдельно про LOB, потому что это самая незаметная часть. Хранилища значения и неограниченные строки лежат не в основных страницах таблицы, и увидеть их вес можно так:
SELECT o.name AS table_name, SUM(CASE WHEN au.type = 1 THEN au.total_pages ELSE 0 END) * 8 / 1024.0 AS in_row_mb, SUM(CASE WHEN au.type IN (2, 3) THEN au.total_pages ELSE 0 END) * 8 / 1024.0 AS lob_mb FROM sys.allocation_units au JOIN sys.partitions p ON p.partition_id = au.container_id JOIN sys.objects o ON o.object_id = p.object_id AND o.type = 'U' GROUP BY o.name HAVING SUM(CASE WHEN au.type IN (2, 3) THEN au.total_pages ELSE 0 END) > 0 ORDER BY 3 DESC
Тип 2 это LOB_DATA, тип 3 это ROW_OVERFLOW_DATA. Если у таблицы во второй колонке единицы мегабайт, а в третьей десятки гигабайт, вы нашли ровно тот случай, который оценка по метаданным не увидит никогда: записей мало, реквизитов мало, а вес есть.
Как проверить это у себя за десять минут
Не верьте моим числам, они с одной базы. Проверка простая:
- Снимите факт запросом выше, отсортируйте по размеру, возьмите первые десять таблиц.
- Запустите любой инструмент, который считает объёмы по метаданным, и возьмите его первые десять.
- Посчитайте пересечение.
Если у вас база с длинной историей бухгалтерии, ставлю на то, что верхушки разойдутся: у меня 3 из 10. Если разойдутся сильнее, интересно узнать в комментариях, на какой конфигурации.
Отдельно посмотрите, есть ли в вашем списке служебные таблицы регистров. Если их нет вовсе, а регистр бухгалтерии в базе живой, то больше терабайта у вас может лежать вне отчёта, как в моём случае.
Что я поменял у себя
Замер закончился правилом, которое теперь действует для всех наших инструментов: инструмент не подаёт оценочное число как рейтинг. Там, где факт доступен, инструмент обязан брать факт. Там, где нет, результат выводится списком кандидатов с явной оговоркой о точности, а место в списке не называется ответом.
Это дороже в поддержке и хуже выглядит в описании: "покажу тридцать кандидатов" звучит слабее, чем "покажу, что занимает место". Зато не отправляет человека чистить не ту таблицу.
Другие наши инструменты диагностики 1С:
- Карта объёмов базы 1С - та самая оценка по метаданным, по которой шёл замер. После этой статьи её первую строку читать как ответ нельзя, а как список кандидатов она работает.
- Чек-ап СУБД под 1С - если доступа к SQL Server нет, приём тот же, что в статье: обработка печатает диагностический скрипт, администратор его выполняет, обработка разбирает ответ и выносит вердикты.
- Журнал транзакций переполнен - гигабайты, которых нет ни в одной таблице и потому нет ни в какой оценке по метаданным. Частый ответ на "база выросла за ночь".
- Тестовая база из бэкапа рабочей - чтобы проверку из предыдущего раздела гонять на свежей копии, а не на проде.
Вопрос к тем, кто дочитал
Я считаю, что оценку по метаданным вообще не стоит показывать как список с местами: она полезна как фильтр кандидатов и вредна как рейтинг. Но есть и другая позиция, которую я слышал: даже кривой порядок лучше, чем ничего, если человек понимает, что это оценка.
Мой контраргумент простой: понимает не человек, а надпись под таблицей, и читают её единицы. Первая строка отчёта работает как ответ независимо от оговорок.
Если у вас есть способ считать размер по метаданным так, чтобы верхушка не разъезжалась, напишите механику. Заполненность строк из метаданных не выводится, и я не вижу, откуда её взять без обращения к данным. Но замер у меня один, база одна, и это ровно тот случай, когда я буду рад ошибиться.
Вступайте в нашу телеграмм-группу Инфостарт