In questi giorni in azienda ho seguito corso molto interessante sul tuning di Sql Server, tenuto da Andrea Benedetti che saluto e ringrazio per la sua simpatia e per le grandi conoscenze.
Durante queste giornate abbiamo individuato due problemi dovuti alla configurazione errata di NHibernate che potevano degradare le performance dell’applicazione.
Il primo problema si presenta quando nei file di mapping non vengono indicati i tipo di dati e viene lasciato ad NHibernate il compito di dedurli.
<class name="Customer" table="customer_tb" lazy="false">
<id name="IdCustomer" column="idCustomer" unsaved-value="0">
<generator class="native" />
</id>
<property name=”CustomerName" column="customerName" />
</class>
exec sp_executesql N'SELECT * FROM customer WHERE customerName = @p0', N'@p0 nvarchar(5), @p0 = N'Rossi'
exec sp_executesql N'SELECT * FROM customer WHERE customerName = @p0', N'@p0 nvarchar(4), @p0 = N'Neri'
In questo esempio il primo comando crea un piano di esecuzione con il parametro @p0 a nvarchar(5) che viene inserito nella cache dei piani di esecuzione.
Quando viene eseguito il secondo comando, il piano di esecuzione precedente non può essere utilizzato perchè stavolta @p0 vale nvarchar(4) essendo Neri è di 4 caratteri.
Questo comporta un degrado delle prestazioni non solo per il tempo di calcolo del nuovo piano di esecuzione ma anche nella ricerca dei piani di esecuzione in cache.
Il secondo problema riguarda l’utilizzo errato del HQL, in questo caso nell’applicazione venivano scritte query senza utilizzare i parametri e quindi ancora una volta i piani di esecuzione non venivano memorizzati correttamente.
Per parametrizzare correttamente le espressioni HQL è sufficiente aggiungere alla query il nome del parametro preceduto da : e successivamente con i vari metodi Set impostarne i valori.
IQuery query = session.CreateQuery(@"select c from Customer c
where c.CustomerName = :name");
query.SetString("name", "Rossi");
IList<Customer> result = query.List<Customer>();