zubkov-andrei / pg_profile

Postgres historic workload reports
Other
228 stars 33 forks source link

Определение размеров таблиц #16

Closed ideev closed 2 years ago

ideev commented 3 years ago

Андрей, на конференции Вы делились проблемой, которая связана с блокировками при попытке определить объем файлов. Хотел бы на всякий случай напомнить один способ, который мог бы быть полезен в данной ситуации, например:

copy tbl_file_size from program 'ls -l base/13676'; 

Копируем вывод команды OS в таблицу с помощью SQL-команды COPY, далее можно распарсить данные, сгруппировав цифры по объему файлов относительно OID. Наверное, это не так уж удобно, но может помочь решить проблему.

zubkov-andrei commented 3 years ago

Вылезать из базы данных в shell очень не хочется. Это неуниверсально, небезопасно и ненадёжно.

ideev commented 3 years ago

Оказывается, есть встроенные функции! Привожу запрос на основе своего примера:

select q.file_name, (pg_stat_file('base/13675/'||q.file_name)).size 
  from (select *  from pg_ls_dir('base/13675') file_name) q;
Guzya commented 3 years ago

А постгрес случайно, не хранит количество сегментов\файлов таблицы?

zubkov-andrei commented 3 years ago

@Guzya, к большому сожалению, не хранит. И это, в частности, является могучим недостатком механизмов резервного копирования и восстановления. В ходе восстановления из бэкапа не существует способа надежно убедиться в том, что восстановлены все сегменты отношений. Слава богу, есть pg_class.relpages - этого хватило бы, если бы это поле заполнялось не вакуумом, а бэкендами в момент расширения отношения. @ideev, функции есть, но от этого как-то не легче - во-первых, процесс измерения размеров всех объектов в базе данных получается всё равно очень сложным - отношения бьются на сегменты (обычно по 1 ГБ), которые придется находить и складывать. Потом, этот механизм придется поддерживать если в перспективе появятся дополнительные форки или стораджи, которые будут вести себя иначе. Я очень опасаюсь косяков в это месте - когда я говорю что я измерил размер отношения - это должен быть размер отношения, а не самим мной придуманный механизм по измерению размеров каких-то файлов. А завтра у отношений появятся сегменты, не входящие в него (COW-снимки, или что-то в этом роде). Нельзя допускать различных способов измерения одних и тех же величин. Если есть стандартный механизм в postgres, то надо использовать именно его.

ideev commented 3 years ago

Насчет "очень сложно" не могу согласиться, схема именования файлов довольно прозрачна (к OID добавляются суффиксмы .1, .2 и т.д). Плюс еще _fsm, _vm. Но да, надо учитывать нюансы с размерами более 1Gb, а также еще и файлы для TOAST... Но в принципе, подход вполне рабочий, понятно, что это workaround, зато никаких блокировок нет. Насчет возможных сторонних вариантов хранилищ - тут, конечно, сложно сказать. Offtop, но было бы интересно посмотреть на реализацию какого-либо работающего подключаемого хранилища (специально пока не интересовался примерами). Вроде бы в PGPro как раз собирались сделать несколько вариантов. Может, уже есть что-то... В любом случае, спасибо за пример озвученной проблемы - до этого не знал, что есть проблема с блокировками при использовании функций, возвращающих размеры таблиц. Было интересно разобраться, как можно будет обойти при необходимости.

glushakov commented 3 years ago

А если есть кастомный тейблспейс то надо проверять еще и его. Или разработчики решат ещё что нибудь переименовать (как, например pg_xlog в pg_wal) , то придётся костылить проверку еще и на версии... :)

zubkov-andrei commented 2 years ago

В релизе 0.3.5 применен компромиссный подход: Теперь в каждом снимке собираются данные _pgclass.relpages. Сбор данных о размерах отношений с помощью функции _pg_relationsize() можно сделать редким или отключить вовсе, используя политики измерения размеров отношений. При сборе отчета _pgprofile для каждого отношения определяет во всех ли снимках, где требуется наличие размера отношения есть данные, полученные с помощью функции _pg_relationsize(). Если хотя бы в одном снимке за интервал отчета точно измеренных данных нет, то все расчеты, связанные с размерами отношения производятся по данных _pgclass.relpages. В отчете такие измерения будут указаны в квадратных скобках, намекая на то что данные могут сильно отличаться от действительности. Если точные размеры отношений собираются редко, но в отчете надо получить точные данные о росте отношений, то параметр _withgrowth функции _getreport() позволяет автоматически расширить границы интервала до ближайших снимков с точными размерами. Это обсуждение я пока закрываю, если возникнут новые соображения, пишите.