Найефективніший спосіб додати послідовний стовпчик до величезної таблиці


10

Який найшвидший спосіб додати БІГСЕРІАЛЬНИЙ стовпчик до величезної таблиці (~ 3 млрд. Рядків, ~ 174 Гб)?

Редагувати:

  • Я хочу, щоб у стовпці були збільшені значення для існуючих рядків ( NOT NULL).
  • Я не встановив фулфактор (це виглядає як погане рішення в ретроспективі).
  • У мене немає проблеми з дисковим простором, просто хочу, щоб це було якомога швидше.

Відповіді:


12

Що не так з:

ALTER TABLE foo ADD column bar bigserial;

Буде заповнено унікальними значеннями автоматично (починаючи з 1).

Якщо потрібно номер для кожного існуючого рядка, кожен рядок таблиці має бути оновлений . Або ні?

Таблиця буде роздута вдвічі більше, якщо вона не зможе використати мертві кортежі або вільний простір на сторінках даних. Виконання операції може отримати багато користі від FILLFACTORменших ніж 100 або просто випадкових мертвих кортежів, розкинутих по столу. Інакше ви можете запустити VACUUM FULL ANALYZEзгодом, щоб відновити місце на диску. Однак це не буде швидким.

pgstattuple
Вас може зацікавити це розширення. Це допомагає вам збирати статистику на своїх таблицях. Щоб дізнатися про мертві кортежі та вільний простір:

Встановіть розширення один раз у базі даних:

CREATE EXTENSION pgstattuple;

Виклик:

SELECT * FROM pgstattuple('tbl');

Альтернатива

Якщо ви можете дозволити собі створити нову таблицю, яка б розбивала залежно від поглядів, зовнішніх ключів, ...

Створіть порожню копію старої таблиці:

CREATE new_tbl AS
SELECT *
FROM   old_tbl
LIMIT  0;

Додати стовпчик bigserial:

ALTER new_tbl ADD column bar bigserial;

ВСТАВИТИ дані зі старої таблиці, автоматично заповнюючи bigserial:

INSERT INTO new_tbl
SELECT *    --  new column will be filled with default
FROM   old_tbl
ORDER  BY something; -- or don't order if you don't care: faster

Новий стовпчик bigserial відсутній у SELECT INSERT і автоматично заповнюватиметься за замовчуванням . Ви можете прописати всі стовпці та додати nextval()до SELECTсписку такий же ефект.

Переконайтеся, що ви отримали всі свої дані в новій таблиці.
Додайте індекси, обмеження, тригери, які ви мали у старій таблиці зараз .

DROP TABLE old_tbl;
ALTER TABLE new_tbl RENAME TO old_tbl;

Це може бути трохи швидше в цілому. Це залишає вас з ванільним столом (та індексами) без жодного набряку.

Вам потрібний вільний простір на диску - приблизно розмір старої таблиці, залежно від стану таблиці - як приміщення для хитання. Але вам може знадобитися стільки ж, як і для першого простого методу через роздуття столу. Знову ж таки, деталі залежать від стану вашої таблиці.


3
Загорніть альтернативу в одну транзакцію, це буде набагато швидше. Це дозволить уникнути додаткових fsyncs
Frank Heikens
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.