Datos redundantes en las declaraciones de actualización

Hibernate genera instrucciones UPDATE , que incluyen todas las columnas, independientemente de si estoy cambiando el valor en esas columnas, por ejemplo:

 tx.begin(); Item i = em.find(Item.class, 12345); i.setA("a-value"); tx.commit(); 

emite esta statement de UPDATE :

 update Item set A = $1, B = $2, C = $3, D = $4 where id = $5 

para que las columnas B, C, D estén actualizadas, mientras que yo no las cambié.

Decir, los elementos se actualizan con frecuencia y todas las columnas están indexadas. La pregunta es: ¿tiene sentido optimizar la parte de Hibernate a algo como esto?

 tx.begin(); em.createQuery("update Item i set ia = :a where i.id = :id") .setParameter("a", "a-value") .setParameter("id", 12345) .executeUpdate(); tx.commit(); 

Lo que más me confunde es que los planes EXPLAIN de la versión de consulta ‘no optimizada’ y ‘optimizada’ son idénticos.

    Debido a PostgreSQL MVCC , una UPDATE es casi como DELETE más un INSERT , con la notable excepción de los valores tostados. Ver:

    • ¿Postgres reescribe toda la fila en la actualización?

    Para ser precisos, la fila “eliminada” es simplemente invisible para cualquier transacción que se inicie después de que se haya confirmado la eliminación, y se eliminó posteriormente. Por lo tanto, en el lado de la base de datos, incluida la manipulación del índice, en realidad no hay diferencia entre las dos declaraciones. (Se aplican excepciones, sigue leyendo.) Aumenta un poco el tráfico de red (según tus datos) y necesita un poco de análisis.

    Estudié algunas actualizaciones de HOT después de la entrada de @ araqnid y realicé algunas pruebas. Las actualizaciones en columnas que en realidad no cambian el valor no hacen ninguna diferencia en lo que respecta a las actualizaciones de HOT. Mi respuesta es válida. Vea los detalles abajo.

    Esto también se aplica a los atributos tostados, ya que estos tampoco se tocan a menos que los valores realmente cambien .

    Sin embargo , si usa desencadenadores por columna (presentados con la página 9.0), esto puede tener efectos secundarios no deseados.

    Cito el manual sobre desencadenantes :

    … un comando como UPDATE ... SET x = x ... activará un disparador en la columna x , aunque el valor de la columna no haya cambiado .

    Negrita énfasis mío.

    Las capas de abstracción son por conveniencia. Son útiles para desarrolladores analfabetos de SQL o si la aplicación debe ser portátil entre diferentes RDBMS. En el lado negativo, pueden dañar el rendimiento e introducir puntos de falla adicionales. Los evito siempre que sea posible.

    Con respecto a las actualizaciones de HOT (Heup-only tuple)

    Las Tuplas de solo montón se introdujeron con Postgres 8.3 , con importantes mejoras en 8.3.4 y 8.4.9 .
    Las notas de la versión de Postgres 8.3:

    UPDATE s y DELETE dejan atrás las tuplas muertas, al igual que INSERT s fallidas. Previamente solo VACUUM podría reclamar espacio tomado por tuplas muertas. Con HOT, el espacio de tupla muerto se puede reclamar automáticamente al momento de INSERT o UPDATE si no se realizan cambios en las columnas indexadas . Esto permite un rendimiento más consistente. Además, HOT evita agregar entradas de índice duplicadas.

    Énfasis mío Y “sin cambios” incluye casos en los que las columnas se actualizan con el mismo valor que ya tienen. De hecho, lo probé hace un momento, ya que no estaba seguro.

    Las columnas tostadas tampoco se interponen en el camino de las actualizaciones CALIENTES. La tupla actualizada en HOT solo se vincula a la misma tupla (s) sin modificar en la bifurcación de brindis de la relación. Las actualizaciones HOT incluso funcionan con valores tostados en la lista de objectives (realmente modificada o no). Si se cambian los valores tostados, esto implica escribir en la bifurcación de la relación de tostado, obviamente. Probé todo eso, también.

    No tienes que creer en mi palabra. Vea por usted mismo, Postgres proporciona un par de funciones para verificar las estadísticas . Ejecute su UPDATE con y sin todas las columnas y verifique si hace alguna diferencia.

     -- Number of rows HOT-updated in table: SELECT pg_stat_get_tuples_hot_updated('table_name'::regclass::oid) -- Number of rows HOT-updated in table, in the current transaction: SELECT pg_stat_get_xact_tuples_hot_updated('table_name'::regclass::oid) 

    O use pgAdmin . Seleccione su tabla e inspeccione la pestaña “Estadísticas” en la ventana principal.

    Tenga en cuenta que las actualizaciones HOT solo son posibles cuando hay espacio para la nueva versión de tupla en la misma página de la bifurcación de relación principal. Una forma simple de forzar esa condición es probar con una tabla pequeña que contenga solo unas pocas filas. El tamaño de página suele ser de 8k, por lo que debe haber espacio libre en la página.

    Puede usar la anotación de hibernación @Entity:

     @org.hibernate.annotations.Entity(dynamicUpdate = true) public class Item 

    Esto solo actualizará los campos modificados.