I need to optimize a query that is being produced by a save (insert query) on a domain entity. I've configured NHibernate using Fluent NHibernate.
Here's the query generated by NHibernate during the insertion of a user's response to a poll:
exec sp_executesql N'INSERT INTO dbo.Response (ModifiedDate, IpAddress, CountryCode,
IsRemoteAddr, PollId) VALUES (@p0, @p1, @p2, @p3, @p4); select SCOPE_IDENTITY()',N'@p0
datetime,@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 bit,@p4 int',
@p0='2001-07-08 03:59:05',@p1=N'127.0.0.1',@p2=N'US',@p3=1,@p4=2
If one looks at the input parameters for IpAddress
and CountryCode
, one will notice that NHibernate is using nvarchar(4000)
. The problem is that nvarchar(4000)
is far larger than I need for either IpAddress
or CountryCode
and due to high traffic and hosting requirements I need to optimize the database for memory usage.
Here's the Fluent NHibernate auto-mapping overrides for those columns:
mapping.Map(x => x.IpAddress).CustomSqlType("varchar(15)");
mapping.Map(x => x.CountryCode).CustomSqlType("varchar(6)");
This isn't the only place that I see unnecessary nvarchar(4000)'s popping up.
How do I control NHibernate's usage of nvarchar(4000)
for string representation?
How do I change this insert
statement to use the proper sized input parameters?
Here is a work around, if you want to replace all nvarchar with varchar
Then plug it into your config
This issue can cause a huge performance problem in queries if it forces SQL Server to perform a table scan instead of using an index. We use varchar throughout our database so I created a convention to set the type globally:
Okay this is what we have to do, the
SQLClientDriver
ignores the length property of theSqlType
. So we created a our own driverclass inheriting fromSQLClientDriver
and override the methodGenerateCommand
...Something like this:Specify the
Type
asNHibernateUtil.AnsiString
with aLength
instead of using a CustomSqlType.