Being a part of this discussion in the beginning (and being quoted in
some of the referenced material) I'll give my latest 10 pence to the
discussion. I'm not working on a project with NHibernate right now,
thats why I've been silent.
1) prepare_sql: I wrote that setting prepare_sql was causing the
underlying
ADO.NET layer to generate "prepared" statements instead of
"parameterized" statements. Prepared statements are not wery well
documented by MS, but gives back a handle to the application layer
which can be used to execute the same statement again without
resending the statement sql text (only actual parametervalues). What I
also wrote was that these prepared statements are only connection
local. That it still true when it comes to the handle (representing
the statement), but I later found out that the executionplan that was
generated at the same time is GLOBAL - as we want it to be... So
setting "prepare_sql = true", sqlprofiler shows us a lot of sp_prepare
statements which gives back new handles for the same statement for new
connections - but the underlying executionplan IS reused (as long as
the size of the parameterdefinitions are unchanged).
Just before version 2.1, Fabio implemented changes so the
typedefinition for strings (which caused the biggest problems) were
sent using the standard size of 4000. This is a OK solution for the
problem sketched above, which requires the typedefinition to be
constant in order to use an existing executionplan. In ver. 2.1 some
bugs concerning size of binaryblobs and decimals not being set
correctly were also fixed.
All in all my conclusion is that setting prepare_sql = true for
NHibernate later than ver. 2.1 IS a viable solution in order to reuse
executionplans (and avoid sending sql text more than once per
connection). You dont need to override the database driver code.
Kind regards
Carsten Hess
You can use this query to check whether your executionplans are reused
(usecounts column):
select top 100 st.text, cp.cacheobjtype, cp.objtype, cp.refcounts,
cp.usecounts, cp.size_in_bytes, cp.bucketid, cp.plan_handle
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) st
where cp.cacheobjtype = 'Compiled Plan'
and cp.objtype = 'Prepared'