Недавно у меня был сервер PostgreSQL 8.2.11, обновленный до 8.4, чтобы использовать возможности автоочистки и соответствовать 30 другим серверам PGSQL. Это было сделано отдельной ИТ-группой, которая администрирует аппаратное обеспечение, поэтому у нас нет большого выбора для других обновлений (некоторое время мы не увидим 9+). Сервер существует в очень закрытой среде (изолированная сеть, ограниченные привилегии root) и работает на RHEL5.5 (i686). После обновления база данных постоянно росла до 5-6 ГБ в день. Обычно база данных в целом составляет ~ 20 ГБ; в настоящее время это ~ 89 ГБ. У нас есть пара других серверов, которые работают с эквивалентными базами данных и фактически синхронизируют записи друг с другом через стороннее приложение (у меня нет доступа к внутренней работе). Другие базы данных ~ 20 ГБ, как и должно быть.
При выполнении следующего SQL-кода совершенно очевидно, что существует проблема с конкретной таблицей, а точнее с ее таблицей TOAST.
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Который производит:
отношение | размер ------------------------------------ + --------- pg_toast.pg_toast_16874 | 89 ГБ twos00.warmstates | 1095 МБ ... (20 рядов)
Эта таблица TOAST предназначена для таблицы, называемой «временной серией», в которой хранятся большие записи данных большого размера. A SUM(LENGTH(blob)/1024./1024.)
из всех записей во временных сериях дает ~ 16 ГБ для этого столбца. Не должно быть никаких причин, по которым таблица TOAST этой таблицы должна быть такой же большой, как и она.
Я выполнил VACUUM FULL VERBOSE ANALYZE timeseries
, и вакуум работает до конца без ошибок.
ИНФОРМАЦИЯ: очистка "pg_toast.pg_toast_16874"
ИНФОРМАЦИЯ: "pg_toast_16874": найдено 22483 сменных, 10475318 неустранимых версий строк на 10448587 страницах
ПОДРОБНОЕ ОПИСАНИЕ : 0 версий мертвых строк еще не могут быть удалены.
Неизменяемые версии строк имеют длину от 37 до 2036 байт.
Были 20121422 неиспользованных указателей предметов.
Общий объем свободного места (включая версии съемных строк) составляет 0 байт. 4944885 страниц являются или станут пустыми, включая 0 в конце таблицы. 4944885 страниц, содержащих 0 свободных байтов, являются потенциальными местами перемещения.
Процессор 75,31 с / 29,59u с истек 877,79 с.
ИНФОРМАЦИЯ: индекс «pg_toast_16874_index» теперь содержит 10475318 версий строк на 179931 страницах
. ПОДРОБНЕЕ: 23884 версии строк индекса были удалены.
101623 страницы индекса были удалены, 101623 в настоящее время могут использоваться повторно.
Процессор 1,35 с / 2,46u сек. Прошло 21,07 с.
Переиндексирована таблица , которая освобожденная некоторое пространство (~ 1 Гб). Я не могу кластеризовать таблицу, так как на диске недостаточно места для процесса, и я жду полной перестройки таблицы, поскольку мне хотелось бы выяснить, почему она намного больше, чем у эквивалентных баз данных, которые у нас есть.
Запустил запрос из вики PostgreSQL здесь - «Показать раздувание базы данных» , и вот что я получаю:
current_database | имя схемы | имя таблицы | тблоат | wastedbytes | Инаме | иблоат | wastedibytes ----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + -------------- ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | idx_timeseries_synchlevel | 0.0 | 0 ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | idx_timeseries_localavail | 0.0 | 0 ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | idx_timeseries_expirytime | 0.0 | 0 ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | idx_timeseries_expiry_null | 0.0 | 0 ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | uniq_localintid | 0.0 | 0 ptrdb04 | Несколько00 | временные ряды | 1.0 | 0 | pk_timeseries | 0,1 | 0 ptrdb04 | Несколько00 | idx_timeseries_expiry_null | 0,6 | 0 | ? | 0.0 | 0
Похоже, что база данных вообще не считает это пространство «пустым», но я просто не вижу, откуда берется все дисковое пространство!
Я подозреваю, что этот сервер баз данных решает использовать в 4-5 раз больше дискового пространства для сохранения тех же записей, которые извлекаются с других серверов данных. У меня такой вопрос: есть ли способ проверить размер физического диска в строке? Я хотел бы сравнить размер одной строки в этой базе данных с другой "здоровой" базой данных.
Спасибо за любую помощь, вы можете предоставить!
ОБНОВЛЕНИЕ 1
Я закончил тем, что восстановил таблицу из сброшенной схемы из-за ее размера (не мог оставить это в покое в течение другого дня). После синхронизации данных через программный процесс синхронизации таблица TOAST составляла ~ 35 ГБ; однако из этого столбца BLOB-объектов я мог получить только ~ 9 ГБ, что должно быть самым длинным с точки зрения значений. Не уверен, откуда поступают остальные 26 ГБ. КЛАСТЕР, ВАКУУМ ПОЛНЫЙ, И ПОВТОРЕННЫЙ безрезультатно. В postgresql.conf файлы между локальными и удаленными серверами баз данных в точности то же самое. Есть ли какая-либо причина, по которой эта база данных пытается хранить каждую запись с большим пространством на диске?
ОБНОВЛЕНИЕ 2 - Исправлено
В конце концов я решил полностью перестроить базу данных с нуля, вплоть до переустановки пакетов PostgreSQL84 в системе. Путь к базе данных был повторно инициализирован, а табличные пространства очищены. Сторонний процесс синхронизации программного обеспечения заново заполнил таблицы, и окончательный размер оказался ~ 12 ГБ ! К сожалению, это никоим образом не помогает решить, какой именно источник проблемы был здесь. Я собираюсь просмотреть его в течение дня или двух и посмотреть, есть ли какие-либо существенные различия в том, как обновленная база данных обрабатывает таблицу TOAST, и выложить эти результаты здесь.
Размер отношения
ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04-> pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04-> FROM pg_class C
ptrdb04-> LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04-> WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04-> ORDER BY pg_relation_size(C.oid) DESC
ptrdb04-> LIMIT 2;
отношение | размер
------------------------- + ---------
pg_toast . pg_toast_17269 | 18 ГБ
fews00 . теплые состояния | 1224 МБ
( 2 строки )
VACUUM VERBOSE ANALYZE timeseries;
ИНФОРМАЦИЯ: «временные ряды»: найдено 12699 съемных, 681961 несъемных версий строк в 58130 из 68382 страниц ДЕТАЛИ: 0 версий мертвых строк еще не могут быть удалены. Было 105847 неиспользованных указателей предметов. 0 страниц полностью пусты. Процессор 0,83 с / 2,08u с прошел 33,36 с. ИНФОРМАЦИЯ: пылесос "pg_toast.pg_toast_17269" ИНФОРМАЦИЯ: отсканированный индекс "pg_toast_17269_index" для удаления 2055849 версий строк ДЕТАЛИ: ЦП 0,37 с / 2,92 с прошло 13,29 с. ИНФОРМАЦИЯ: "pg_toast_17269": удалены версии строк 2055849 на 518543 страницах ДЕТАЛИ: ЦП 8,60 с / 3,21 с прошло 358,42 с. ИНФОРМАЦИЯ: индекс "pg_toast_17269_index" теперь содержит 7346902 версий строк на 36786 страницах ПОДРОБНОЕ: 2055849 версии строки индекса были удалены. 10410 страниц индекса были удалены, 5124 в настоящее время могут использоваться повторно. CPU 0.00s / 0.00u сек. Прошло 0,01 сек. ИНФОРМАЦИЯ: "pg_toast_17269": найдено 1286128 съемных, 2993389 несъемных версий строк в 1257871 из 2328079 страниц ДЕТАЛИ: 0 версий мертвых строк еще не могут быть удалены. Было 18847 неиспользованных указателей предметов. 0 страниц полностью пусты. Процессор 26,56 с / 13,04 с прошел 714,97 с. ИНФОРМАЦИЯ: анализируя "lesss00.timeseries" ИНФОРМАЦИЯ: «timeseries»: отсканировано 30000 из 68382 страниц, содержащих 360192 живых строк и 0 мертвых строк; 30000 строк в выборке, 821022 расчетных строк
Единственная заметная разница после восстановления (кроме использования диска)
ИНФОРМАЦИЯ: "pg_toast_17269": найдено 1286128 съемных, 2993389 несъемных версий строккак @CraigRinger упоминается в комментарии. Количество несменяемых строк намного меньше, чем раньше.
Новый вопрос: могут ли другие таблицы влиять на размер другой таблицы? (через внешние ключи и тому подобное) Перестройка таблицы ничего не дала, но перестройка всей базы данных доказала, что проблема решена.