2012-05-02 2 views
2

В моем проекте, имеющем 23 миллиона записей и около 6 полей, индексируется в этой таблице.Добавить новый столбец без блокировки стола?

Раньше я тестировал, чтобы добавить дельта-столбец для поиска Thinking Sphinx, но он поворачивается, удерживая всю блокировку базы данных в течение часа. После этого, когда файл добавляется, и я пытаюсь перестроить индексы это запрос, который удерживает блокировку базы данных в течение приблизительно 4 часов:

"update user_messages set delta = false where delta = true" 

Ну для создания сервера до Я создал новую базу данных из БД отвала и продвигать его как база данных, поэтому сервер может быть включен в живую.

Теперь, что я ищу, это то, что добавление столба дельта в моем столе с блокировкой стола возможно? И как только добавляется столбец delta, то почему этот запрос выполняется при запуске команды перестройки индекса и почему он так долго блокирует сервер?

PS .: Я нахожусь на Heroku и используя Postgres с моделью ika db.

ответ

2

Обновление в PostgreSQL означает запись новой версии строки. Ваш вопрос не содержит всю информацию, но это, вероятно, означает запись миллионов новых строк.

Если ваша модель данных и свободное дисковое пространство позволяют, CREATE новой таблицы в фоновом режиме, а затем, в одной транзакции: DROP старого стол, RENAME новой.
Подробности и оговорки в этом related later answer on dba.SE.

Кроме того, если затронута значительная часть таблицы, удалите все индексы перед массой UPDATE, так как все индексы также должны быть обновлены. Быстрее удалять их и воссоздавать их после завершения массового UPDATE.

И, наконец, при создании новой таблицы в фоновом режиме: Применить все изменения сразу или создать несколько обновленных версий затронутых строк.

Отказ от ответственности: добавление нового столбца без DEFAULT (= DEFAULT NULL) обычно не создает новую строку и очень дешево само по себе. Добавление в него значений создает новые строки.
Details in the maunal.

Если вы не можете удалить исходную таблицу из-за ограничений, другой быстрый способ построить временную таблицу, TRUNCATE оригинал один и масса INSERT новые строки - сортируют, если это повышает производительность. Все в одной транзакции. Что-то вроде этого:

BEGIN 

SET temp_buffers = 1000MB; -- or whatever you can spare temporarily 

CREATE TEMP TABLE tmp AS 
SELECT * FROM tbl LIMIT 0; -- copy layout of table 

ALTER TABLE tmp ADD column delta boolean; -- NOT DEFAULT 

INSERT INTO tmp (col1, col2, ... , delta) 
SELECT col1, col2, ... , FALSE 
FROM tbl;    -- copy existing rows plus new value 
-- ORDER BY ??? 

-- DROP all indexes here 

TRUNCATE tbl;    -- empty table - truncate is super fast 

ALTER TABLE tbl ADD column delta boolean DEFAULT FALSE; -- NOT NULL? 

INSERT INTO tbl 
SELECT * FROM tmp;   -- insert back surviving rows. 

-- recreate all indexes here 

COMMIT; 
0

Вы можете добавить еще один стол с одним столбцом, таких длинных замков не будет. Конечно, в первом столбце должен быть другой столбец, внешний ключ.

Для индексов вы можете использовать «CREATE INDEX CONCURRENTLY», он не использует слишком тяжелые блокировки в этой таблице http://www.postgresql.org/docs/9.1/static/sql-createindex.html.

Смежные вопросы