java - update - spring querydsl subquery




Tests de performances entre QueryDSL SQL et JDBCTemplate (2)

J'essaie de convaincre "les plus hauts" d'utiliser SQLS querydsl pour notre persistance. Mais ils préfèrent le jdbctemplate de printemps, car il donne la meilleure performance brute.

La performance est notre principale exigence. Ce qui explique pourquoi JPA n'est pas une option du tout. Le surdébit SQL QueryDSL est-il trop important pour l'éliminer de nos options?

Je voulais savoir s'il y avait des tests de performance "récents" pour montrer comment les tarifs sql de querydsl avec jdbctemplate et jpa.

Je suis tombé sur ça . Je veux connaître les performances relatives de querydsl sql par rapport à jdbctemplate et une implémentation jpa.


J'ai fait quelques tests de performance pour comparer les frais généraux / performances entre querydsl et jdbctemplate.

Voici ce que j'ai fait
1. Créé un projet de démarrage de printemps qui utilise querydsl et jdbctemplate
2. Créé 2 points de terminaison, 1 pour l'utilisation de querydsl et un autre pour jdbctemplate.
3. La configuration querydsl utilise la source de données auto-configurée spring boot pour configurer son SQLQueryFactory.
4. JdbcTemplate est également configuré automatiquement avec la même source de données autoconfigurée.
5. Il existe 2 implémentations d'une requête similaire dans le référentiel, l'une utilise querydsl et l'autre utilise jdbctemplate. La requête est relativement complexe et consiste en un couple de jointures internes et de clauses where.
6. Les méthodes Service ont une boucle for et appellent la méthode repository dans chaque itération. Nombre d'itérations est configurable et a été réglé à 1 itérations lakh.
7. System.nanoTime () est utilisé autour de la méthode de service dans le contrôleur pour calculer le temps nécessaire à l'exécution de nombreuses itérations de la méthode du référentiel.
8. JdbcTemplate a pris en moyenne 800ms pour exécuter des appels de dépôt de 1 lakh.
9. Querydsl a pris en moyenne 5000ms pour exécuter des appels de dépôt de 1 lakh.
10. Observation: Querydsl est 6 fois plus lent que JdbcTemplate pour la même requête. La surcharge est vraisemblablement dans la requête sérialisation de querydsl.

Implémentation du référentiel QueryDSL

List<Customer> customers = new ArrayList<>();
Customer customerObj = null;
List<Tuple> customerTuples =queryFactory.select(customer.firstName,customer.status,customer.customerId).
                                from(customer).innerJoin(customerChat).on(customer.customerId.eq(customerChat.senderId)).
                                innerJoin(customerChatDetail).on(customerChat.chatDetailId.eq(customerChatDetail.chatDetailId)).
                                where(customerChatDetail.isRead.eq(true).and(customer.status.eq(true))).fetch();

    for (Tuple row : customerTuples) {
        customerObj = new Customer();
      customerObj.setFirstName(row.get(customer.firstName));
      customerObj.setStatus( row.get(customer.status));
      customerObj.setCustomerId(row.get(customer.customerId));
      customers.add(customerObj);
    }
return customers;

Implémentation de JdbcTemplate

List<Customer> customers = this.jdbcTemplate.query(
            "select first_name,status,customer_id from customer inner join v_customer_chat on customer.customer_id=v_customer_chat.sender_id inner join v_customer_chat_detail on v_customer_chat.chat_detail_id = v_customer_chat_detail.chat_detail_id where v_customer_chat_detail.is_read = ? and customer.status = ?;",new Object[] {true, true},
            new RowMapper<Customer>() {
                public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Customer customer = new Customer();
                    customer.setFirstName(rs.getString("first_name"));
                    customer.setStatus(rs.getBoolean("status"));
                    customer.setCustomerId(rs.getLong("customer_id"));
                    return customer;
                }
            });  

Fondamentalement, j'essaie de faire exactement la même chose avec différentes bibliothèques et de mesurer celles qui encourent plus de frais généraux.
1. Exécutez une requête relativement complexe avec des jointures.
2. Remplissez les beans du jeu de résultats.

J'utilise la base de données H2 In-memory. La base de données ne contient que quelques enregistrements pour chaque table. Et 1 ligne de résultats qui correspond à la requête.

La méthode est exécutée dans une boucle for (1 itération lakh). Et le temps calculé à l'aide de System.nanoTime () autour de la boucle.

C'est un projet de démarrage à ressort avec différents points d'extrémité (un pour querydsl et un autre pour jdbctemplate). La configuration de querydsl et queryfactory est effectuée comme suit

  @Autowired
public DataSource dataSource;

@Bean
public PlatformTransactionManager transactionManager() {
    return new DataSourceTransactionManager(dataSource);
}

@Bean
public com.querydsl.sql.Configuration querydslConfiguration() {
    SQLTemplates templates = H2Templates.builder().build();
    com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);

    configuration.setExceptionTranslator(new SpringExceptionTranslator());

    return configuration;
}

@Bean
public SQLQueryFactory queryFactory() {
    Provider<Connection> provider = new SpringConnectionProvider(dataSource);
    return new SQLQueryFactory(querydslConfiguration(), provider);
}

Profil votre application et voir ce qui prend le temps dans la requête. Est-ce l'analyse et la compilation de la requête, ou la requête elle-même?

Ecrivez-vous des requêtes qui renvoient l'ensemble de l'objet de domaine ou un sous-ensemble de colonnes (en utilisant la structure de type JPA "select new BlaBlaDTO")?

Avez-vous envisagé d'utiliser Spring Data JPA où vous avez un contrôle total sur l'utilisation de RAW SQL, des requêtes nommées ou des conventions de dénomination de la méthode Spring Data JPA?

Votre configuration de connexion JDBC met-elle en mémoire cache les instructions préparées du côté de la base de données, de sorte qu'elles ne doivent être préparées qu'une seule fois pour la même requête avec des paramètres différents (cela fait une énorme différence)?

Utilisez-vous un cache de premier et second niveau pour améliorer les performances côté serveur?

La sélection de JDBC brut comme mécanisme préféré finira par être horrible; requêtes complexes, pas de vérification sale, pas de verrouillage optimiste, etc.





querydsl