3 votes

Performance des requêtes SQL natives et JPA

Je dispose des méthodes suivantes. La première est une requête SQL native et la seconde est une requête JPA.

@Query(value = "SELECT  id                  AS id," +
            "       col1                        AS col1," +
            "       col2                        AS col2," +
            "       col3                        AS col3," +
            "       col4                        AS col4," +
            "       col5                        AS col5," +
            "       col6                        AS col6," +
            "       col7                        AS col7," +
            "       col8                        AS col8," +
            "       col9                        AS col9," +
            "       col10                       AS col10," +
            "       col11                       AS col11," +
            "       col12                       AS col12," +
            "       col13                       AS col13" +
            "FROM foo " +
            "WHERE id = :id AND col1 = :col1", nativeQuery = true)
    List<Foo> findFooByIdAndCol1(@Param("id") final Long id, @Param("col1") final Long col1);

List<FooEntity> findByIdAndCol1(Long id, Long col1);

Journaux

----Native sql -----
2020-02-26 10:17:04.908 DEBUG 3888 --- [           main] org.hibernate.SQL                        : SELECT id AS id, col1 AS col1, col2 AS col2, col3 AS col3, col4 AS col4, col5 AS col5, col6 AS col6, col7 AS col7, col8 AS col8, col9 AS col9, col10 AS col10, col11 AS col11, col12 AS col12, col13 AS col13 FROM foo WHERE id = ? AND col1 = ?
2020-02-26 10:17:04.915 TRACE 3888 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2020-02-26 10:17:04.915 TRACE 3888 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [1]

-----JPA query -----
2020-02-26 10:17:04.956 DEBUG 3888 --- [           main] org.hibernate.SQL                        : select foo0_.id as id1_0_, foo0_.col1 as col1_0_, foo0_.col2 as col2_3_0_, foo0_.col3 as col3_4_0_, foo0_.col4 as col4_5_0_, foo0_.col5 as col5_6_0_, foo0_.col6 as col6_7_0_, foo0_.col7 as col7_8_0_, foo0_.col8 as col8_9_0_, foo0_.col9 as col9_10_0_, foo0_.col10 as col10_20_0_, foo0_.col11 as col11_11_0_, foo0_.col12 as col12_12_0_, foo0_.col13 as col13_13_0_, foo0_.col14 as col14_14_0_, foo0_.col15 as col15_0_, foo0_.col16 as col16_16_0_, foo0_.col18 as col18_17_0_, foo0_.col19 as col19_18_0_, foo0_.col20 as col120_19_0_ from foo foo0_ where foo0_.id=? and foo0_.col1=?
2020-02-26 10:17:04.956 TRACE 3888 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2020-02-26 10:17:04.956 TRACE 3888 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [1]

Il semble que lorsqu'il s'exécute, il émet la même requête dans les journaux. J'ai testé cela avec 10k enregistrements dans la base de données. Requête native : 54.7s JPA : 74s

Est-ce que la requête SQL native est meilleure que JPA dans mon cas d'utilisation ? Ou existe-t-il des solutions pour améliorer les performances de JPA ? (Note : Je sais qu'il y a la pagination et les types de fetch etc. Mais ce n'est pas ce que je recherche)

4voto

Simulant Points 4329

Le code SQL effectif exécuté sur la base de données doit être le même. Vous devez donc faire attention à ce que vous mesurez et à l'usage que vous voulez faire du résultat.

JPA est conçu pour mettre à jour et stockage Les modèles de données orientés objet sont transformés en structures de données relationnelles, de sorte qu'il n'est pas nécessaire de mettre en œuvre manuellement le mappage des collections et des relations.

Ainsi, le résultat de votre requête JPA est géré dans l'EntityManager et les modifications apportées à vos résultats peuvent facilement être réenregistrées. Alors que la requête native est juste une sélection avec une projection dans un objet de résultat, qui n'est pas géré par votre EntityManager. Vous supprimez donc l'overhead de l'EntityManager avec la requête native, mais vous n'avez pas de SQL optimisé.

La première question à se poser n'est donc pas "qu'est-ce qui est plus rapide ?", mais "quel est votre cas d'utilisation ?". Si vous souhaitez afficher des résultats en lecture seule, vous pouvez utiliser la requête native et économiser des frais généraux, ce qui réduit le temps d'exécution dans l'ensemble. Si vous souhaitez stocker les modifications apportées à vos résultats dans la base de données, vous devriez utiliser la requête JPA et vous pourriez également vouloir mesurer l'opération de stockage.

En fonction du cas d'utilisation, il est également possible d'opter pour un code plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X