2016-06-30 49 views
8

Sto cercando di convincere "i più alti" di utilizzare querydsl sql per la nostra persistenza. Ma preferiscono spring jdbctemplate, con la ragione che è la migliore prestazione grezza.Test delle prestazioni tra QueryDSL SQL vs JDBCTemplate

La prestazione è il nostro requisito principale del corso. Ecco perché l'APP non è affatto un'opzione. Il sovraccarico SQL di QueryDSL è troppo importante per eliminarlo dalle nostre opzioni?

Volevo sapere se sono stati eseguiti test di prestazioni "recenti" per mostrare come query sql sql fa riferimento a jdbctemplate e jpa.

Mi sono imbattuto in this. Voglio conoscere le prestazioni relative di querydsl sql se confrontato con jdbctemplate e un'implementazione jpa.

+0

Un po 'come _ "Assembler (o C) è più veloce." _ Non riuscirai mai a convincerli pro QueryDSL a meno che non ci siano casi d'uso che traggano vantaggio dall'intelligenza incorporata. Così fai qualche riscrittura, forse troverai alcune cose: errori in SQL, notazione breve, ottimizzazioni in QueryDSL, SQL risultante. –

+1

Capisco che si tratti di compromessi tra prestazioni non elaborate e compatibilità degli sviluppatori (manutenibilità). Quello che voglio dimostrare (o mi aspetto) è che QueryDSL SQL fornisce prestazioni notevolmente migliori rispetto a JPA/ORM ed è solo "leggermente" sovraperformato da JDBCTemplate. Sono alla ricerca di alcuni fatti/figure per questo. Nel frattempo, sto provando anche io alcune prove. –

risposta

11

Ho eseguito alcuni test delle prestazioni per confrontare la parzializzazione sovraccarico/prestazioni tra querydsl e jdbctemplate.

Ecco che cosa ho fatto
1. Creato un progetto di avvio molla che utilizza querydsl e jdbctemplate
2. Creato 2 punti finali, 1 per l'utilizzo di querydsl e un altro per jdbctemplate.
3. La configurazione di querydsl utilizza l'origine dati autofigurata di avvio di primavera per configurare SQLQueryFactory.
4. JdbcTemplate viene inoltre configurato automaticamente con la stessa origine dati autoconfigurata.
5. Ci sono 2 implementazioni di una query simile nel repository, una usa querydsl e l'altra usa jdbctemplate. La query è relativamente complessa e consiste in un paio di join interni e clausole in cui.
6. I metodi di servizio hanno un ciclo for e chiama il metodo repository in ogni iterazione. No. di iterazioni è configurabile ed è stato impostato su 1 ciclo di iterazioni.
7. System.nanoTime() viene utilizzato attorno al metodo di servizio nel controller per calcolare il tempo impiegato per eseguire le numerose iterazioni del metodo di repository.
8. JdbcTemplate ha impiegato una media di 800 ms per eseguire 1 chiamate lakh di repository.
9. Querydsl ha impiegato una media di 5000 ms per eseguire 1 chiamate lakh di repository.
10. Osservazione: Querydsl è 6 volte più lento di JdbcTemplate per la stessa query. Il sovraccarico è presumibilmente nella serializzazione della query di querydsl.

QueryDSL Attuazione Repository

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; 

JdbcTemplate Attuazione

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; 
       } 
      }); 

Fondamentalmente sto cercando di fare la stessa cosa con diverse librerie e misura che uno incorre più in alto.
1. Eseguire una query relativamente complessa con join.
2. Popolare i bean dal set di risultati.

Sto utilizzando il database in memoria H2. Il database contiene solo un paio di record per ogni tabella. E 1 riga di risultati che corrisponde alla query.

Il metodo viene eseguito in un ciclo for (1 ciclo di iterazioni). E tempo calcolato con l'aiuto di System.nanoTime() attorno al ciclo.

È un progetto di avvio a molla con diversi endpoint (uno per querydsl e un altro per jdbctemplate). La configurazione per querydsl e queryfactory viene eseguita come segue

@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); 
} 
1

Profilo la tua app e vedere che cosa sta prendendo il tempo nella query. È l'analisi e la compilazione della query o la query stessa?

Stai scrivendo query che restituiscono l'intero oggetto dominio o un sottoinsieme di colonne (utilizzando il costrutto di tipo "seleziona nuovo BlaBlaDTO" di JPA)?

Hai considerato l'utilizzo di Spring Data JPA in cui hai il pieno controllo sull'utilizzo di SQL RAW, query denominate o metodi JPA di Spring Data che citano le query della convenzione?

La configurazione della connessione JDBC è in grado di memorizzare in cache le istruzioni preparate sul lato del database in modo che sia necessario prepararle una sola volta per la stessa query con parametri diversi (ciò rappresenta un'enorme differenza)?

Si sta utilizzando una cache di primo e secondo livello per migliorare le prestazioni lato server?

Il prelievo di JDBC non elaborato come meccanismo preferito finirà per essere terribile; query complesse, nessun controllo sporco, nessun blocco ottimistico ecc.

0

Ammen.M se stai cercando prestazioni in termini di accesso al database (in piattaforma JavaEE) l'opzione migliore è pura JDBC, ma tutti conoscono i suoi limiti e il ampio uso di stringhe con SQL nativo. Spring Data, JPA o QueryDSL, tutti questi framework offrono a voi altri vantaggi come sicurezza del tipo, mappatura relazionale tra tabelle e oggetti.

Quindi, se la tua squadra è davvero preoccupata per le prestazioni che dovrebbero essere la tua scommessa.