Привет PostgreSQL гуру!
Я ищу несколько советов по поводу производительности PostgreSQL в отношении импорта "больших" пакетов данных.
Весь процесс довольно прост. У меня есть база данных BigQuery, которую я загружаю в базу данных sqlite3. А затем после некоторой обработки мне нужно закачать данные в PostgreSQL. Я использую Python 3.6.9 для извлечения данных из базы данных sqlite3 в кадр данных (используя read_sql_query) ... это занимает секунды - 12 с для самого большого набора записей из 3.388.566 записей - в настоящее время работает в течение 11 часов и до сих пор не законченный. Затем я использую многопоточность Python, чтобы порождать 8 потоков, каждый из которых загружает 1/8 данных в 8192 больших кусках.
На основании исследований и тестов, которые я провел с Python против PostgreSQL импорта Я использую метод с StringIO, который «записывает» dataframe.to_csv, а затем copy_from для подачи в базу данных PostgreSQL.
Все это прекрасно работало, пока я не начал использовать индексы. Я прекрасно понимал, что это повлияет на производительность нагрузки, но без них производительность запросов была просто ужасна, поэтому мне нужно их использовать. Данные являются данными события и, таким образом, содержат метку времени с полем tz, пару полей uuid, некоторые поля varchars и dbl pre c. Всего 11 полей, 5 из них проиндексированы (1 отметка времени и 4 поля uuid). Средняя длина записи составляет ок. 170 байт. В таблице есть приложение. 3,4 ГБ размера и 20,3 млн записей. И кстати, автоматический вакуум включен.
Конфигурация сервера: DigitalOcean CPU-оптимизированный дроплет
- 8 выделенных виртуальных ЦП (Intel Xeon Skylake (2,7 ГГц, 3,7 ГГц турбо)
- 16 ГБ ОЗУ
- 25 ГБ SSD плюс том 50 ГБ SSD (подключен, но не используется
- ОС - Ubuntu 18
- PostgreSQL Версия сервера - 11,6 (Ubuntu 11,6- 1.pgdg18.04 + 1)
Сервер работает на 100% -ной загрузке ЦП - все 8 ЦП усердно работают, чтобы выполнить работу. И они работали хорошо, пока БД не получила немного больше См. результаты ниже:
Date Records Duration Seconds Recs/Sec
01.11.19 53 761 00:00:05 5 10 043
10.11.19 20 314 00:00:06 6 3 233
20.11.19 23 278 00:00:13 14 1 683
30.11.19 12 495 00:00:11 11 1 133
10.12.19 25 771 00:00:20 20 1 286
20.12.19 52 448 00:00:52 52 1 007
30.12.19 29 872 00:00:44 44 674
10.01.20 32 852 00:00:56 57 578
20.01.20 45 569 00:01:26 86 530
21.01.20 558 118 00:02:24 144 3 876
22.01.20 2 472 590 01:11:26 4 286 577
23.01.20 3 873 271 05:11:53 18 713 207
24.01.20 2 126 177 03:44:25 13 465 158
25.01.20 1 486 789 03:35:42 12 942 115
26.01.20 1 367 299 04:04:45 14 685 93
27.01.20 2 648 854 10:20:30 37 230 71
28.01.20 3 276 999 16:17:44 58 664 56
Переход от 10K записей в секунду до 50 записей в секунду заставляет меня думать, что я, должно быть, сделал что-то не так! Я просмотрел много рекомендаций и страниц об импорте и изменил конфигурацию БД исходя из этого (только отличие от значения по умолчанию):
max_connections = 20
shared_buffers = 2GB
work_mem = 1GB
maintenance_work_mem = 10GB
max_worker_processes = 16
max_parallel_maintenance_workers = 1
max_parallel_workers_per_gather = 1
max_parallel_workers = 16
max_wal_size = 16GB
min_wal_size = 4GB
effective_cache_size = 8GB
Я решил использовать разбиение таблиц, но потом прочитал, что это более актуально для больших баз данных, таких как 100 ГБ +. это т Если бы я разбил данные по метке времени с помощью tz, что (согласно моим прочтениям) усложнилось. Но я бы так и сделал. Просто подумайте, что 3,5 ГБ данных приложения. 20M записей недостаточно для этого.
Может кто-нибудь, пожалуйста, посоветовать, как управлять таким импортом? В настоящее время количество записей составляет от 2 до 4 миллионов записей в день. Но это может резко возрасти очень скоро, и я хочу иметь возможность сделать эту передачу данных как можно быстрее. Данные не изменятся! Поэтому я испытывал желание выключить WAL, но был разочарован тем, что после cra sh я потеряю все данные.
В идеальной ситуации я хотел бы достичь хотя бы начальных 10K записей / se c на этой машине. ;) Есть идеи, как этого добиться?
Кстати: это не обязательно должно быть Python, sqlite3, dataframe, et c. Просто все, что подойдет!
Большое спасибо заранее, том. +
PS: Может быть, PostgreSQL тоже не подходящая БД.
Обновление от 13 февраля 2020 г .: УКАЗАТЬ И УСТРАНИТЬ ПОВТОРНЫЕ ИНДЕКСЫ - процесс необходимо запускать повторно. Это не единственный выстрел. Моя идея - запускать его хотя бы раз в час. Поэтому я не могу удалить индексы и заново создавать их каждый раз. Это было бы (я полагаю) довольно неэффективно.
Чтобы использовать ЦП, я использовал top:
top - 21:12:21 up 1:32, 3 users, load average: 6.31, 2.42, 2.00
Tasks: 169 total, 9 running, 92 sleeping, 0 stopped, 0 zombie
%Cpu(s): 69.6 us, 29.9 sy, 0.0 ni, 0.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 16424524 total, 6811228 free, 1309644 used, 8303652 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 13289704 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3574 postgres 20 0 2348648 1.448g 1.445g R 99.3 9.2 1:43.13 postgres
3562 postgres 20 0 2348648 1.418g 1.415g R 99.0 9.1 1:43.18 postgres
3567 postgres 20 0 2348648 1.448g 1.445g R 99.0 9.2 1:43.09 postgres
3573 postgres 20 0 2348644 1.448g 1.445g R 99.0 9.2 1:43.15 postgres
3566 postgres 20 0 2348644 1.447g 1.444g R 98.7 9.2 1:42.54 postgres
3570 postgres 20 0 2348648 1.448g 1.445g R 98.7 9.2 1:43.04 postgres
3564 postgres 20 0 2348648 1.448g 1.445g R 98.3 9.2 1:42.96 postgres
3569 postgres 20 0 2348648 1.448g 1.445g R 98.3 9.2 1:42.36 postgres
1088 root 20 0 9966.9m 990.8m 30208 S 0.3 6.2 1:56.49 java
Вывод vmstat 1:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
8 0 0 6813372 29668 8272692 0 0 170 4 541 1014 19 20 61 0 0
8 0 0 6813116 29668 8272716 0 0 0 0 2309 46147 77 23 0 0 0
8 0 0 6813116 29668 8272732 0 0 0 0 2308 45379 76 24 0 0 0
8 0 0 6812992 29676 8272764 0 0 0 76 2289 45297 75 25 0 0 0
8 0 0 6812992 29676 8272840 0 0 0 0 2297 45654 74 26 0 0 0
8 0 0 6812992 29676 8272864 0 0 0 0 2310 40172 72 28 0 0 0
8 0 0 6812992 29676 8272872 0 0 0 0 2360 35028 66 34 0 0 0
8 0 0 6812992 29676 8272880 0 0 0 0 2295 36441 71 29 0 0 0