Использование PG 9.1 в Ubuntu 12.04.
В настоящее время нам требуется до 24 часов для выполнения большого набора операторов UPDATE в базе данных, которые имеют вид:
UPDATE table
SET field1 = constant1, field2 = constant2, ...
WHERE id = constid
(Мы просто перезаписываем поля объектов, идентифицированных по ID.) Значения поступают из внешнего источника данных (еще нет в БД в таблице).
Таблицы имеют несколько индексов и не имеют ограничений по внешнему ключу. Коммит не делается до конца.
Для импорта pg_dump
всей БД требуется 2 часа . Это похоже на базовый уровень, на который мы должны разумно ориентироваться.
Если не считать создание специальной программы, которая каким-то образом восстанавливает набор данных для PostgreSQL для повторного импорта, есть ли что-то, что мы можем сделать, чтобы приблизить объемную производительность UPDATE к производительности импорта? (Это та область, в которой, по нашему мнению, деревья слияния с лог-структурой хорошо обрабатываются, но нам интересно, можно ли что-нибудь сделать в PostgreSQL.)
Некоторые идеи:
- сбросить все неидентификационные индексы и восстановить после этого?
- увеличение контрольных точек, но помогает ли это в долгосрочной перспективе?
- используя методы, упомянутые здесь ? (Загрузить новые данные в виде таблицы, затем «объединить» старые данные, где идентификатор не найден в новых данных)
По сути, есть куча вещей, которые можно попробовать, и мы не уверены, какие из них наиболее эффективны, или мы упускаем из виду другие вещи. В следующие несколько дней мы будем проводить эксперименты, но мы подумали, что спросим и здесь.
У меня есть параллельная загрузка таблицы, но она доступна только для чтения.
explain analyze
что он использует индекс для поиска?Ответы:
Предположения
Поскольку информация в Q отсутствует, я буду считать:
COPY
выходные данные, с уникальным значением дляid
каждой строки, чтобы соответствовать целевой таблице.Если нет, сначала отформатируйте его правильно или используйте
COPY
параметры для работы с форматом.Это означает отсутствие одновременного доступа. Еще рассмотрим этот связанный ответ:
Решение
Я предлагаю вам использовать тот же подход, который описан в ссылке из вашего третьего пункта . С серьезной оптимизацией.
Для создания временной таблицы есть более простой и быстрый способ:
Один большой
UPDATE
из временной таблицы внутри базы данных будет на несколько порядков быстрее, чем отдельные обновления извне базы данных.В модели MVCC PostgreSQL -
UPDATE
средство для создания новой версии строки и пометки старой как удаленной. Это примерно так же дорого, какINSERT
и вDELETE
сочетании. Плюс, это оставляет вас с множеством мертвых кортежей. Так как вы в любом случае обновляете всю таблицу, в целом быстрее будет просто создать новую таблицу и удалить старую.Если у вас достаточно ОЗУ, установите
temp_buffers
(только для этого сеанса!) Достаточно высоко, чтобы держать временную таблицу в ОЗУ, прежде чем делать что-либо еще.Чтобы оценить, сколько ОЗУ необходимо, запустите тест с небольшой выборкой и используйте функции размера объекта БД :
Полный сценарий
Параллельная загрузка
Параллельные операции над таблицей (которые я исключил в предположениях в начале) будут ожидать, когда таблица будет закрыта ближе к концу, и завершатся неудачно, как только транзакция будет зафиксирована, поскольку имя таблицы немедленно преобразуется в ее OID, но новая таблица имеет другой OID. Таблица остается согласованной, но параллельные операции могут получить исключение и должны быть повторены. Подробности в этом ответе:
ОБНОВЛЕНИЕ маршрута
Если вам нужно идти по этому
UPDATE
пути, удалите любой индекс, который не нужен во время обновления, и создайте его заново. Гораздо дешевле создать индекс одним куском, чем обновлять его для каждой отдельной строки. Это также может позволить горячие обновления .Я изложил аналогичную процедуру, используя
UPDATE
в этом тесно связанном ответе на SO .источник
DROP TABLE
вынимаетAccess Exclusive Lock
. В любом случае, я уже перечислил обязательное условие в верхней части моего ответа:You can afford to drop and recreate the target table.
это может помочь заблокировать таблицу в начале транзакции. Я предлагаю вам начать новый вопрос со всеми соответствующими деталями вашей ситуации, чтобы мы могли разобраться в этом.CREATE TABLE tbl_new AS SELECT t.*, u.field1, u.field2 from tbl t NATURAL LEFT JOIN tmp_tbl u;
,LEFT JOIN
позволяя сохранять строки, для которых нет обновления. Конечно,NATURAL
можно изменить на любой действительныйUSING()
илиON
.Если данные можно сделать доступными в структурированном файле, вы можете прочитать их с помощью сторонней оболочки данных и выполнить слияние с целевой таблицей.
источник
MERGE
еще не реализован в PostgreSQL (пока). Реализации в других СУБД сильно различаются. Рассмотрим информацию тега дляMERGE
иUPSERT
.