我在ASP.NET应用程序中使用NHibernate连接到MS SQL Server 2005数据库。在某些情况下,我需要编写自己的SQL查询。但是,我注意到每次执行以下代码时SQL服务器线程都会泄漏大约50 KB的内存:
NHibernate.ISession session = NHibernateSessionManager.Instance.GetSession();
ISQLQuery query = session.CreateSQLQuery(
"select {a.*} from t_alarm a where a.deactivationtime > '" +
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") +
"'");
query.AddEntity("a", typeof(TAlarm));
System.Collections.IList aList = query.List();
当我查看Windows任务管理器时,我发现每次运行此代码时,进程sqlservr.exe
会将其内存使用量增加50 KB。
这是非常有趣的部分。如果我在上面的代码中将"yyyy-MM-dd HH:mm:ss"
替换为"yyyy-MM-dd HH:mm"
(即我删除了秒),则内存泄漏会停止。
更新:显然内存泄漏实际上并没有停止。他们只是每分钟显示一次。推测当SQL查询发生变化时。
两种情况下返回的结果都相同。
有没有人知道这里发生了什么?
答案 0 :(得分:2)
您是否已在程序缓存中添加了查询计划?
sqlservr.exe占用内存并且不会释放它,除非必须在其他应用程序需要时释放它。因此,DB服务器是独立的,而不是多用途的。
From BOL: Dynamic Memory Management
在具有2 GB RAM的32位PC上,SQL Server 2000将最多消耗1.7GB RAM。有一篇KB文章描述了这一点。
在这种情况下,通过提供秒,您隐式声明“datetime”类型,而不是“smalldatetime”类型。这可能会影响您的查询计划。您可能会对“a.deactivationtime”进行隐式转换
答案 1 :(得分:2)
A) 在示例中,您没有正确处理NHibernate的Session,因此与DB的连接保持打开状态。
使用(){} statemenet或尝试{} cath {} finally {}来正确关闭连接。
b)您编写的SQL命令不使用SQL参数,因此每次执行时,SQL服务器都会将其视为一个新命令 - 更准确地说是每秒(或者如果删除:ss部分,则每分钟删除)。使用SQL参数(如使用HQL,Criteria或QBE查询时的NHibernate),它将以较少的内存消耗正确缓存。
希望这会有所帮助;)