sql >> Base de Datos >  >> RDS >> PostgreSQL

Comprensión de las operaciones por lotes de JDBC

Puede haber varios tipos de procesamiento por lotes involucrados, y cubriría parte del controlador JDBC de PostgreSQL (pgjdbc).

TL; DR:pgjdbc usa menos red roundrips en caso de que se use la API por lotes. BatchedQuery se usa solo si reWriteBatchedInserts=true se pasa a la configuración de conexión pgjdbc.

Puede encontrar https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance relevante (diapositiva 44,...)

Cuando se trata de la ejecución de consultas, la latencia de la red suele ser una parte importante del tiempo transcurrido.

Supongamos que el caso es insertar 10 filas.

  1. Sin procesamiento por lotes (por ejemplo, solo PreparedStatement#execute en bucle). El conductor realizaría lo siguiente

    execute query
    sync <-- wait for the response from the DB
    execute query
    sync <-- wait for the response from the DB
    execute query
    sync <-- wait for the response from the DB
    ...
    

    Se gastaría un tiempo notable en la "espera del DB"

  2. API por lotes de JDBC. Eso es PreparedStatement#addBatch() permite que el controlador envíe múltiples "ejecuciones de consultas" en un solo viaje de ida y vuelta a la red. Sin embargo, la implementación actual seguiría dividiendo los lotes grandes en lotes más pequeños para evitar el interbloqueo de TCP.

    Las acciones serían mucho mejores:

    execute query
    ...
    execute query
    execute query
    execute query
    sync <-- wait for the response from the DB
    
  3. Tenga en cuenta que incluso con #addBatch , hay una sobrecarga de los comandos "ejecutar consulta". El servidor tarda un tiempo considerable en procesar cada mensaje individualmente.

    Una de las formas de reducir el número de consultas es utilizar la inserción de valores múltiples. Por ejemplo:

    insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
    

    Este PostgreSQL permite insertar varias filas a la vez. El inconveniente es que no tiene un mensaje de error detallado (por fila). Actualmente, Hibernate no implementa la inserción de valores múltiples.

    Sin embargo, pgjdbc puede reescribir inserciones por lotes regulares en valores múltiples sobre la marcha desde el 9.4.1209 (2016-07-15).

    Para activar la reescritura de valores múltiples, debe agregar reWriteBatchedInserts=true propiedad de conexión. La función se desarrolló inicialmente en https://github.com/pgjdbc/pgjdbc/pull/491

    Es lo suficientemente inteligente como para usar 2 declaraciones para insertar 10 filas. La primera es una declaración de 8 valores y la segunda es una declaración de 2 valores. El uso de potencias de dos permite que pgjdbc mantenga la cantidad de declaraciones distintas, y eso mejora el rendimiento, ya que las declaraciones de uso frecuente están preparadas por el servidor (consulte ¿Cuál es la vida útil de una declaración preparada del lado del servidor de PostgreSQL)

    BatchedQuery representa ese tipo de declaraciones de varios valores, por lo que verá que la clase se usa en reWriteBatchedInserts=true solo caso.

    Los inconvenientes de la función pueden incluir:detalles más bajos como el "resultado del lote". Por ejemplo, el lote regular le da "por recuento de filas de declaración", sin embargo, en el caso de valores múltiples, solo obtiene el estado de "sentencia completada". Además de eso, el reescritor sobre la marcha puede fallar al analizar ciertas declaraciones SQL (por ejemplo, https://github.com/pgjdbc/pgjdbc/issues/1045).