Pisanie ponad 50 milionów z Pyspark df do PostgresSQL, najbardziej efektywne podejście


16

Jaki byłby najbardziej efektywny sposób wstawiania milionów rekordów, mówi 50 milionów z ramki danych Spark do tabel Postgres. Robiłem to od Spark do MSSQL w przeszłości, korzystając z opcji kopiowania zbiorczego i opcji wielkości partii , która również się powiodła.

Czy istnieje coś podobnego dla Postgres?

Dodanie kodu, który próbowałem i czasu potrzebnego do uruchomienia procesu:

def inserter():
    start = timer()
    sql_res.write.format("jdbc").option("numPartitions","5").option("batchsize","200000")\
    .option("url", "jdbc:postgresql://xyz.com:5435/abc_db") \
    .option("dbtable", "public.full_load").option("user", "root").option("password", "password").save()
    end = timer()
    print(timedelta(seconds=end-start))
inserter()

Więc zastosowałem powyższe podejście dla 10 milionów rekordów i miałem 5 równoległych połączeń, jak określono w, numPartitionsa także próbowałem wielkości partii 200k .

Całkowity czas potrzebny na proces wyniósł 0: 14: 05.760926 (czternaście minut i pięć sekund).

Czy istnieje inne skuteczne podejście, które skróciłoby czas?

Jakiego efektywnego lub optymalnego rozmiaru partii mogę użyć? Czy zwiększenie wielkości mojej partii przyspieszy pracę? Czy otwieranie wielu połączeń, tj.> 5, pomaga mi przyspieszyć proces?

Na zasadzie średnio 14 minut na 10 milionów płyt nie jest złe , ale patrząc na ludzi, którzy tam zrobiłby to wcześniej, aby pomóc odpowiedzieć na to pytanie.


1
Możesz najpierw zrzucić dane do lokalnego pliku CSV, a następnie użyć własnych narzędzi importujących PostgreSQL, aby je zaimportować - zależy to od tego, gdzie jest wąskie gardło: czy wolno eksportuje z Pyspark, czy wolno importuje do Postgres, czy coś innego? (To powiedziawszy, 14 minut na 50 milionów wierszy nie wydaje mi się takie złe - jakie indeksy są zdefiniowane w tabeli?).
Dai,

Dai, mam plik df, który ma rozmiar 52 mil, a teraz piszę go do Postgres, to nowy stół, który tworzę na podstawie powyższego kodu. Nie utworzyłem tabeli w Postgres, a potem tam piszę. Czy jest lepsza możliwość, jeśli najpierw mogę utworzyć tabelę i zindeksować ją w Postgres, a następnie wysłać dane z Spark DF?
Chetan_Vasudevan,

2
(Odwrotnie - indeksy spowalniają operacje wstawiania w tabelach, ale przyspieszają wybrane zapytania)
Dai

Dai, więc po prostu tworzę tabelę w Postgres bez indeksu, a następnie próbuję wstawić i zmierzyć moją wydajność?
Chetan_Vasudevan,

Odpowiedzi:


4

Właściwie zrobiłem trochę taką samą pracę jakiś czas temu, ale używając Apache Sqoop.

Powiedziałbym, że aby odpowiedzieć na te pytania, musimy spróbować zoptymalizować komunikację między Spark a PostgresSQL, w szczególności dane przepływające ze Spark do PostgreSql.

Ale bądź ostrożny, nie zapomnij o stronie Spark. Wykonywanie mapPartitions nie ma sensu, jeśli liczba partycji jest zbyt wysoka w porównaniu z maksymalną liczbą połączeń obsługiwanych przez PostgreSQL, jeśli masz zbyt wiele partycji i otwierasz połączenie dla każdej z nich, prawdopodobnie wystąpi następujący błąd org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.

Aby dostroić proces wstawiania, podszedłbym do problemu, wykonując następujące kroki:

  • Pamiętaj, że liczba partycji jest ważna. Sprawdź liczbę partycji, a następnie dostosuj ją na podstawie liczby połączeń równoległych, które chcesz mieć. Możesz chcieć mieć jedno połączenie na partycję, więc sugeruję sprawdzenie coalesce, jak wspomniano tutaj .
  • Sprawdź maksymalną liczbę połączeń obsługiwanych przez instancję postgreSQL i chcesz zwiększyć liczbę .
  • Do wstawiania danych do PostgreSQL zaleca się użycie polecenia COPY . Oto także bardziej rozbudowana odpowiedź na temat przyspieszenia wstawiania postgreSQL.

Wreszcie, nie ma srebrnej kuli do wykonania tej pracy. Możesz skorzystać ze wszystkich wskazówek, o których wspomniałem powyżej, ale tak naprawdę będzie to zależeć od twoich danych i przypadków użycia.


Dbustosp Na pewno wypróbuję powyższe wskazówki, do tego czasu na pewno zasługujesz na poparcie.
Chetan_Vasudevan

@chetan_vasudevan, jeśli podasz więcej szczegółów na temat danych, których używasz, rozmiaru rekordu itp. Jeśli dane są publiczne, mogę spróbować czegoś na własną rękę i porównać czasy.
dbustosp

Dbustosp dane ma 80 kolumn i 55 milionów rekordów. Zacząłem pracować nad sugestiami, które mi dałeś.
Chetan_Vasudevan

@Chetan_Vasudevan Całkowity rozmiar zestawu danych? Jaki jest format danych wejściowych?
dbustosp

@Chetan_Vasudevan Wszelkie aktualizacje?
dbustosp
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.