2015-05-21 3 views
3

Запуск обновления на большой таблице (например, 8 ГБ). Это простое обновление 3 полей в таблице. У меня не возникло проблем с запуском его в postgresql 9.1, это займет 40-60 минут, но это сработало. Я запускаю тот же запрос в базе данных 9.4 (только что созданный, не обновляемый), и он начинает обновление, но затем замедляется. Он использует только ~ 2% CPU, уровень, если IO составляет 4-5 МБ/с, и он сидит там. Никаких блокировок, других запросов или подключений, только это одно обновление SQL на сервере.Обновление большого стола в Postgresql замедляется

SQL ниже. Таблица поиска имеет 12 записей. Поиск может возвращать только одну строку, он разбивает дискретный масштаб (SMALLINT, -32768 .. +32767) на неперекрывающиеся области. Таблицы «src» и «dest» составляют ~ 60 миллионов записей.

UPDATE dest SET 
    field1 = src.field1, 
    field2 = src.field2, 
    field3_id = (SELECT lookup.id FROM lookup WHERE src.value BETWEEN lookup.min AND lookup.max) 
FROM src 
WHERE dest.id = src.id; 

Я думал, что мой диск замедлился, но я могу скопировать 1 Гб файлов параллельно запрашивать выполнение и работает быстро на> 40MB/s и у меня есть только один диск (это виртуальная машина с ISCSI СМИ). На все другие операции с дисками не влияет, имеется большая пропускная способность ввода-вывода. В то же время PostgreSQL просто сидит там очень мало, работает очень медленно.

У меня есть 2 виртуализированных Linux-сервера, один запускает postgresql 9.1, а другой работает 9.4. Оба сервера имеют близкую к идентичной конфигурации postgresql.

Имеет ли кто-либо еще подобный опыт? У меня заканчиваются идеи. Помогите.

Редактировать Запрос «работает» в течение 20 часов Мне пришлось убить соединения и перезагрузить сервер. Удивительно, но не убивала соединение через запрос:

SELECT pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE pid <> pg_backend_pid() AND datname = current_database(); 

и разъединить производится в следующем журнале:

2015-05-21 12:41:53.412 EDT FATAL: terminating connection due to administrator command 
2015-05-21 12:41:53.438 EDT FATAL: terminating connection due to administrator command 
2015-05-21 12:41:53.438 EDT STATEMENT: UPDATE <... this is 60,000,000 record table update statement> 

Также перезагрузка сервера потребовалось много времени, производя следующий журнал:

2015-05-21 12:43:36.730 EDT LOG: received fast shutdown request 
2015-05-21 12:43:36.730 EDT LOG: aborting any active transactions 
2015-05-21 12:43:36.730 EDT FATAL: terminating connection due to administrator command 
2015-05-21 12:43:36.734 EDT FATAL: terminating connection due to administrator command 
2015-05-21 12:43:36.747 EDT LOG: autovacuum launcher shutting down 
2015-05-21 12:44:36.801 EDT LOG: received immediate shutdown request 
2015-05-21 12:44:36.815 EDT WARNING: terminating connection because of crash of another server process 
2015-05-21 12:44:36.815 EDT DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. 

«Почтовый мастер приказал этому серверному процессу откатить текущую транзакцию и выйти, потому что другой серверный процесс вышел из строя и возможно поврежден общая память "- это признак ошибки в PostgreSQL?

Редактировать Я тестировал 9.1, 9.3 и 9.4. Оба 9.1 и 9.3 не испытывают замедления. 9.4 последовательно замедляет крупные транзакции. Я заметил, что при запуске транзакции htop-монитор показывает высокий CPU, а статус процесса - «R» (работает). Затем он постепенно меняется на низкое использование ЦП и статус «D» - диск (см. Снимок экрана Disk waiting). Мой самый большой вопрос: почему 9.4 отличается от 9.1 и 9.3? У меня дюжина серверов, и этот эффект наблюдается по всем направлениям.

+1

ли Вы, недавно обновление с 9,1 до 9,4? Вы запустили «вакуумный анализ» после импорта? – joop

+0

Это совершенно новая установка, а не обновление. Я запускаю 2 автономных Linux-сервера параллельно. База данных была импортирована из файлов CSV, и таблицы становятся явно пылесосами после завершения загрузки книги. Это работало гладко в течение многих лет на 9.1. Похоже, что процесс 9.4 спокойно терпит неудачу и кивает/висит. –

+0

Включена ли репликация или архивирование? Кроме того, как выглядит инструкция обновления? –

ответ

3

Спасибо всем за помощь. Независимо от того, насколько я пытался подчеркнуть разницу в производительности между идентичной конфигурацией 9.4 и предыдущими версиями, никто, похоже, не обратил на это внимания.

Проблема была решена путем отключения прозрачных огромных страниц:

echo never > /sys/kernel/mm/transparent_hugepage/enabled 
echo never > /sys/kernel/mm/transparent_hugepage/defrag 

Вот некоторые ресурсы, я нашел полезным в reserching вопрос:
* https://dba.stackexchange.com/questions/32890/postgresql-pg-stat-activity-shows-commit/34169#34169
* https://lwn.net/Articles/591723/
* https://blogs.oracle.com/linux/entry/performance_issues_with_transparent_huge

+0

да, предыдущие версии по умолчанию не используют огромные страницы. Кстати, вы заметили высокий% sy (системное время сверху) при запуске 9.4? это обычно указывает на такую ​​проблему. – alexius

0

Я бы заподозрил много поиска дисков - 5 МБ/с практически подходит для очень случайного ввода-вывода на обычном (вращающемся) жестком диске.

Поскольку вы постоянно заменяете в основном все свои ряды, я постараюсь установить dest таблицу fillfactor примерно на 45% (alter table dest set (fillfactor=45);), а затем cluster test using test_pkey;. Это позволит размещать обновленные версии строк в одном и том же секторе диска.

Кроме того, используя cluster src using src_pkey;, так что обе таблицы могут иметь данные в том же физическом порядке на диске, что также может помочь.

Также следует помнить vacuum table dest; после каждого обновления, что большие, поэтому старые версии строк могут быть использованы снова в последующих обновлениях.

Ваш старый сервер, вероятно эволюционировали это FILLFACTOR естественно во время нескольких обновлений. На новом сервере он упакован на 100%, поэтому обновленные строки должны быть размещены в конце.

0

Если только несколько из целевых строк фактически обновлены, вы можете избежать создания новых версий строк с помощью DISTICNT FROM. Это может предотвратить много бесполезного дискового трафика.

UPDATE dest SET 
    field1 = src.field1, 
    field2 = src.field2, 
    field3_id = lu.id 
FROM src 
JOIN lookup lu ON src.value BETWEEN lu.min AND lu.max 
WHERE dest.id = src.id 
     -- avoid unnecessary row versions to be generated 
AND  (dest.field1 IS DISTINCT FROM src.field1 
     OR dest.field1 IS DISTINCT FROM src.field1 
     OR dest.field3_id IS DISTINCT FROM lu.id 
     ) 
     ; 
Смежные вопросы