Тут є кілька непорозумінь:
Нуль растровий є НЕ частиною заголовка купи кортежу. За документацію:
Є заголовок фіксованого розміру (займає 23 байти на більшості машин), за ним слід необов'язковий нульовий растровий малюнок ...
Ваші 32 зведені стовпці не викликають сумнівів з двох причин:
Нульове растрове зображення додається на рядок , і лише якщо в рядку є хоча б одне фактичне NULL
значення . Зменшувані стовпці не мають прямого впливу, а лише фактичні NULL
значення. Якщо нульовий растровий файл виділений, він завжди виділяється повністю (все або нічого). Фактичний розмір нульової растрової карти - 1 біт на стовпець, округлений до наступного байта . По поточному коду souce:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
Нульова растрова карта виділяється після заголовка кучного пакета, а за ним - необов'язковий OID, а потім дані рядків Початок даних OID або рядків позначається t_hoff
у заголовку. За вихідним кодом коментаря :
Зауважте, що t_hoff має бути кратним MAXALIGN.
Є один вільний байт після заголовка кучного кортежу, який займає 23 байти. Таким чином, нульова растрова карта для рядків до 8 стовпців ефективно отримує без додаткових витрат. За допомогою 9-го стовпця таблиці t_hoff
висувається ще один MAXALIGN
(як правило, 8) байт, щоб забезпечити ще 64 стовпці. Тож наступний кордон був би у 72 колонах.
Щоб відобразити інформацію управління кластером баз даних PostgreSQL (включаючи MAXALIGN
), приклад типової установки Postgres 9.3 на машині Debian:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
Я оновив інструкції у відповідній відповіді, яку ви цитували .
Все це вбік, навіть якщо ваш ALTER TABLE
випадок викликає перезапис цілої таблиці (що, мабуть, і є, змінюючи тип даних), 250K насправді не так вже й багато, і це було б за лічені секунди на будь-якій половині пристойної машини (якщо тільки рядки незвично великі) . 10 хвилин і більше свідчать про зовсім іншу проблему. Ваша заява чекає, щоб отримати замок на столі, швидше за все.
Зростаюча кількість записів pg_stat_activity
означає більш відкриті транзакції - вказує на паралельний доступ до столу (швидше за все), який повинен чекати завершення операції.
Кілька пострілів у темряві
Перевірте можливе роздуття столу, спробуйте ніжне VACUUM mytable
або більш агресивне VACUUM FULL mytable
- що може зіткнутися з тими ж проблемами одночасності, оскільки ця форма також набуває ексклюзивний замок. Ви можете спробувати pg_repack замість ...
Я б почав з огляду можливих проблем з індексами, тригерами, зовнішнім ключем чи іншими обмеженнями, особливо тими, що стосуються стовпця. Особливо може бути задіяний пошкоджений індекс? Спробуйте REINDEX TABLE mytable;
або DROP
всі їх та повторно додайте їх після ALTER TABLE
тієї ж транзакції .
Спробуйте запустити команду вночі або коли не буде великого навантаження.
Методом грубої сили було б зупинити доступ до сервера, а потім спробувати ще раз:
Без можливості виправити це, може допомогти оновлення до поточної версії або майбутнього 9.4 . Було здійснено декілька вдосконалень для великих таблиць та для блокування деталей. Але якщо в вашій БД щось зламано, ви, мабуть, повинні спершу зрозуміти це.
SET NOT NULL
це не змінює тип, воно лише додає обмеження - але обмеження потрібно перевірити проти таблиці, і це вимагає повного сканування таблиці. 9.4 покращує деякі з цих випадків, приймаючи слабкі замки, але він все ще досить важкий.