Escribiendo más de 50 millones de Pyspark df a PostgresSQL, el mejor enfoque eficiente


16

¿Cuál sería la forma más eficiente de insertar millones de registros? Por ejemplo, 50 millones de un marco de datos de Spark a tablas de Postgres. He hecho esto desde la chispa a MSSQL en el pasado haciendo uso de la opción de copia masiva y tamaño de lote que también fue exitosa.

¿Hay algo similar que pueda estar aquí para Postgres?

Agregué el código que probé y el tiempo que tomó ejecutar el proceso:

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()

Así que hice el enfoque anterior para 10 millones de registros y tuve 5 conexiones paralelas como se especifica en numPartitionsy también probé un tamaño de lote de 200k .

El tiempo total que llevó el proceso fue 0: 14: 05.760926 (catorce minutos y cinco segundos).

¿Existe algún otro enfoque eficiente que reduzca el tiempo?

¿Cuál sería el tamaño de lote eficiente u óptimo que puedo usar? ¿Aumentar el tamaño de mi lote hará el trabajo más rápido? ¿O abrir varias conexiones, es decir,> 5 me ayuda a acelerar el proceso?

En promedio, 14 minutos para 10 millones de registros no está mal , pero buscar personas que hubieran hecho esto antes para ayudar a responder esta pregunta.


1
Primero puede volcar los datos en un archivo CSV local y luego usar las propias herramientas de importación de PostgreSQL para importarlos; depende de dónde esté el cuello de botella: ¿es lento exportar desde Pyspark o lento para importar a Postgres, o algo más? (Dicho esto, 14 minutos para 50 millones de filas no me parece tan malo, ¿qué índices se definen en la tabla?).
Dai

Dai, tengo un df que es 52mil y ahora lo estoy escribiendo en Postgres, es una nueva tabla que estoy creando a través del código anterior. No he creado la tabla en Postgres y luego escribí allí. ¿Existe una mejor posibilidad si puedo crear una tabla primero e indexarla allí en Postgres y luego enviar datos desde spark df?
Chetan_Vasudevan

2
(Es al revés: los índices ralentizan las operaciones de inserción en las tablas, pero aceleran las consultas de selección)
Dai

Dai, ¿entonces creo la tabla en Postgres sin índice y luego trato de insertar y medir mi rendimiento?
Chetan_Vasudevan

Respuestas:


4

Realmente hice el mismo trabajo hace un tiempo pero usando Apache Sqoop.

Diría que para responder a estas preguntas tenemos que intentar optimizar la comunicación entre Spark y PostgresSQL, específicamente los datos que fluyen de Spark a PostgreSql.

Pero ten cuidado, no te olvides del lado Spark. No tiene sentido ejecutar mapPartitions si el número de particiones es demasiado alto en comparación con el número máximo de conexiones que admite PostgreSQL, si tiene demasiadas particiones y está abriendo una conexión para cada una, probablemente tendrá el siguiente error org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.

Para ajustar el proceso de inserción, abordaría el problema siguiendo los siguientes pasos:

  • Recuerde que el número de particiones es importante. Verifique el número de particiones y luego ajústelo en función del número de conexiones paralelas que desea tener. Es posible que desee tener una conexión por partición, por lo que sugeriría verificar coalesce, como se menciona aquí .
  • Verifique el número máximo de conexiones que admite su instancia de postgreSQL y desea aumentar el número .
  • Para insertar datos en PostgreSQL se recomienda usar el comando COPY . Aquí también hay una respuesta más elaborada sobre cómo acelerar la inserción postgreSQL.

Finalmente, no hay una bala de plata para hacer este trabajo. Puede usar todos los consejos que mencioné anteriormente, pero realmente dependerá de sus datos y casos de uso.


Dbustosp Definitivamente probaré los consejos anteriores, hasta entonces te mereces un voto positivo.
Chetan_Vasudevan

@chetan_vasudevan si proporciona más detalles sobre los datos que está utilizando, el tamaño por registro, etc. Si los datos son públicos, puedo probar algo por mi cuenta y comparar los tiempos.
dbustosp

Dbustosp los datos tienen 80 columnas y sus 55 millones de registros. He empezado a trabajar en las sugerencias que me diste.
Chetan_Vasudevan

@Chetan_Vasudevan ¿El tamaño total del conjunto de datos? ¿Cuál es el formato de los datos de entrada?
dbustosp

@Chetan_Vasudevan ¿Alguna actualización?
dbustosp
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.