2014-10-30 7 views
0

У меня есть таблица, как это (больше столбцов, но они будут делать):Postgres - UPDATE становится медленнее, с течением времени

events 
+----------+----------------+--------------------+------------------+------------------+---------+ 
| event_id | user_ipaddress | network_userid | domain_userid | user_fingerprint | user_id | 
+----------+----------------+--------------------+------------------+------------------+---------+ 
|  1 | 127.0.0.1  | 000d7d9e-f3cb-4a08 | 26dc9870c3572519 |  2199066221 |   | 
|  2 | 127.0.0.1  | 000d7d9e-f3cb-4a08 | 26dc9870c3572519 |  2199066221 |   | 
|  3 | 127.0.0.1  | 000d7d9e-f3cb-4a08 | 26dc9870c3572519 |  2199066221 |   | 
|  4 | 127.0.0.1  | 000d7d9e-f3cb-4a08 | 26dc9870c3572519 |  2199066221 |   | 
+----------+----------------+--------------------+------------------+------------------+---------+ 

таблица содержит около 1M записей. Я пытаюсь обновить все записи, чтобы установить user_id.
Для этого я использую очень простой PHP-скрипт.

Я цикл по каждой записи с user_id = NULL и SELECT из всей таблицы, чтобы найти существующий user_id на основе user_ipaddress, network_userid, domain_userid и/или user_fingerprint.

Если ничего не найдено, я сгенерирую уникальный отчет user_id и UPDATE.
Если матч был найден, я сделаю UPDATE запись с корреспондентом user_id.

Запрос выглядит следующим образом:

UPDATE events SET user_id = 'abc' WHERE event_id = '1' 

SELECT часть супер быстро (~ 5 мс).
Часть UPDATE начинается быстро (~ 10 мс), но становится медленнее (~ 800 мс) после нескольких сотен обновлений.

Если я жду около 10-20 минут, он снова станет быстрым.

Я использую PostgreSQL 9.3.3 на AWS RDS (db.m1.medium) с общим хранилищем SSD. У меня есть индексы по всем столбцам, объединенные и индивидуально.

Я играл с FILLFACTOR и в настоящее время он устанавливается на 70. Я попытался запустить VACUUM FULL events, но я никогда не знаю, закончилось ли это (ждали более 1 часа). Также я пробовал REINDEX TABLE events.

Я единственный, кто пользуется этим сервером.

Вот EXPLAIN ANALYZE из UPDATE запроса:

Update on events (cost=0.43..8.45 rows=1 width=7479) (actual time=0.118..0.118 rows=0 loops=1) 
    -> Index Scan using events_event_id_idx on events (cost=0.43..8.45 rows=1 width=7479) (actual time=0.062..0.065 rows=1 loops=1) 
     Index Cond: (event_id = '1'::bpchar) 
Total runtime: 0.224 ms 

Любые хорошие идеи о том, как я могу сохранить запрос быстро?

+0

Можете ли вы показать «EXPLAIN ANALYZE» на длинном «UPADATE»? –

+0

"cost = 0.43..8.45" hmmm .... [См. Слайд 13] (https://wiki.postgresql.org/images/4/45/Explaining_EXPLAIN.pdf) – bishop

+0

@IgorRomanchenko, в моем вопросе есть длинный индекс UPDATE –

ответ

0

Я обнаружил, что проблема была вызвана файловой выбранной для моего экземпляра RDS. Я бежал с General Purpose Storage (SSD). По-видимому, он имеет некоторые ограничения ввода-вывода. Таким образом, решение заключалось в переключении хранилища. Теперь я запускаю Provisioned IOPS Storage, и производительность улучшилась мгновенно.

Кроме того, решение может заключаться в том, чтобы придерживаться General Purpose Storage (SSD) и увеличить размер хранилища, поскольку это также увеличит пределы ввода-вывода.

Подробнее: http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html#Concepts.Storage.GeneralSSD

Спасибо за все ответы. И спасибо @Dan и @ArtemGr за то, что указали мне в этом направлении.

0

За 10-20 минут, чтобы стать быстрым снова, вы получаете постепенное улучшение?

Вещи, которые я бы проверить:

  • вы создаете новые соединения с каждым обновлением и оставить их открытыми? Затем они будут таймаутом и закрываться через некоторое время.
  • Что такое системная нагрузка (CPU, память, IO)? Я действительно задавался вопросом, может ли экземпляр поддерживать всплески, но я так не думаю.
+0

Да, я действительно вижу постепенное улучшение. Если я перезапущу свой процесс, первые 10 обновлений будут довольно быстрыми. Вот статистика от AWS: http://i.imgur.com/ZP2d6vh.png http://i.imgur.com/1bFhCMO.png –

+0

Я использую одно и то же соединение для всех запросов (выбирает, обновляет) –

+0

Что такое файловая система? Некоторые файловые системы (например, BTRFS) имеют такое поведение (например, замедление после накопления большого количества операций записи в процесс). Также это может быть кеш обратной записи SSD, и вы нажимаете на его пределы. Может, что-то в этом роде? http://www.howtogeek.com/165542/why-solid-state-drives-slow-down-as-you-fill-them-up/ – ArtemGr

0

Я просто догадываюсь, Это потому, что ваш первичный ключ - это char не int. Попробуйте преобразовать ваш первичный ключ в int и увидеть результат.

Вашего объяснить проанализируют результат говорит Index Cond: (event_id = '1'::bpchar)

  1. Лучший выбор для первичного ключа являются целыми типами данных, так как целые значения процесса быстрее, чем значения типа данных символов. Символьный тип данных (как первичный ключ) перед обработкой должен быть преобразован в эквивалентные значения ASCII.
  2. Получение записи на основе первичного ключа будет быстрее в случае целых чисел в качестве ключей приоритета, так как это будет означать, что на одной странице будут присутствовать более индексные записи. Таким образом, общее время поиска уменьшается. Также соединения будут быстрее. Но это применимо, если ваш запрос использует поиск кластеризованного индекса, а не сканирование, и если используется только одна таблица. Если сканирование не будет иметь дополнительный столбец, это будет означать большее количество строк на одной странице данных.

SQL Index - Difference Between char and int

+0

Event_id не является целым числом. Я использовал 1,2,3,4 для упрощения. Я вижу, что это плохая идея. Простите за это.Событие_ид похоже: fd057117-596e-4973-9eef-8fe338354820 –

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