Avere strano problema di prestazioni usando Hibernate 3.3.2GA dietro JPA (e il resto dei pacchetti inclusi in Hibernate JBoss 5.)JPA (Hibernate) nativo di query per la dichiarazione preparata SLOW
sto usando Native Query e assemblando SQL in una dichiarazione preparata.
EntityManager em = getEntityManager(MY_DS);
final Query query = em.createNativeQuery(fullSql, entity.getClass());
L'SQL ha molti join, ma in realtà è molto semplice, con un singolo parametro. Ad esempio:
SELECT field1, field2, field3 FROM entity left join entity2 on... left join entity3 on
WHERE stringId like ?
e la query viene eseguita in meno di un secondo su MSSQL Studio.
Se aggiungo
query.setParameter(0, "ABC123%");
la query una pausa di 9 secondi
2012-01-20 14:36:21 - TRACE: - AbstractBatcher.getPreparedStatement:(484) | preparing statement
2012-01-20 14:36:21 - TRACE: - StringType.nullSafeSet:(133) | binding 'ABC123%' to parameter: 1
2012-01-20 14:36:30 - DEBUG: - AbstractBatcher.logOpenResults:(382) | about to open ResultSet (open ResultSets: 0, globally: 0)
Tuttavia, se basta sostituire il "?" con il valore (rendendolo non una dichiarazione preparata, ma solo una query SQL dritto.
fullSql = fullSql.replace("?", "'ABC123%'");
la query completare in meno di un secondo.
Vorrei davvero preferisco noi una dichiarazione preparata (la ingresso per i parametri viene estratta dai dati utente) per prevenire attacchi di iniezione.
Tracciare lungo il punto lento nel codice, sono arrivato in profondità all'interno del pacchetto jtds-1.2.2. la riga all'origine sembra essere SharedSocket linea 841 "getIn(). readFully (hdrBuf);" Non c'è nulla di ovvio lì però ...
private byte[] readPacket(byte buffer[])
throws IOException {
//
// Read rest of header
try {
getIn().readFully(hdrBuf);
} catch (EOFException e) {
throw new IOException("DB server closed connection.");
}
Arrivati a questo stack attraverso ...
at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:841)
at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:722)
at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:466)
at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:103)
at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:88)
at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3928)
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1045)
at net.sourceforge.jtds.jdbc.TdsCore.microsoftPrepare(TdsCore.java:1178)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareSQL(ConnectionJDBC2.java:657)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:776)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
at org.hibernate.loader.Loader.doQuery(Loader.java:697)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2228)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
at org.hibernate.loader.Loader.list(Loader.java:2120)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1722)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
Consentitemi di aggiungere jtds-1.2.2 allo stack tecnologico. Ho eseguito il debugging tramite Hibernate in JTDS – javatestcase
provato jtds-1.2.4, ma nessuna gioia ... – javatestcase
Passare a com.microsoft.sqlserver.jdbc.SQLServerDriver produce effettivamente risultati identici ... Devo dare un'occhiata a SQL Server, forse c'è qualcosa ... – javatestcase