我知道这里已经发布了类似的问题:NHibernate - first query is painfully slow。不幸的是,它没有提供有效的答案。
基本上,问题是第一个NHibernate查询需要大约1000毫秒才能运行。我可以通过使用纯SQL查询将滞后降低到600毫秒。我们正在使用Castle.ActiveRecord。
查询很简单:通过用户名从DB获取用户对象。
return FindFirst(Expression.Eq("UserName", userName));
可以像这样创建表:
CREATE TABLE [dbo].[USER](
[USER_ID] [int] NOT NULL,
[COMPANY_ID] [int] NULL,
[USER_NAME] [varchar](100) NOT NULL,
[PASSWORD] [varchar](100) NOT NULL,
[ENABLED] [char](1) NOT NULL,
[SUPER_USER] [char](1) NOT NULL,
[EMAIL] [varchar](100) NULL,
[LAST_ACCESS] [datetime] NULL,
[PREVIOUS_LOGIN] [datetime] NULL,
[FIRST_NAME] [varchar](200) NULL,
[LAST_NAME] [varchar](200) NULL,
[CONTACT_INFO] [varchar](200) NULL,
[CULTURE] [varchar](20) NULL DEFAULT ('sl-SI'),
CONSTRAINT [PK_USER] PRIMARY KEY CLUSTERED
(
[USER_ID] ASC
))
GO
以下是我们创建索引的方式:
CREATE UNIQUE NONCLUSTERED INDEX [IX_USER_NAME] ON [dbo].[USER]
(
[USER_NAME] ASC
))
GO
用户对象:
[ActiveRecord("USER", Lazy=true)]
public partial class User : ActiveRecordBase<User>
{
[PrimaryKey("USER", "USER_ID")]
public virtual int UserId { get; set; }
[BelongsTo("COMPANY_ID")]
public virtual Company RealCompany { get; set; }
[Property("USER_NAME")]
public virtual string UserName { get; set; }
[Property("PASSWORD")]
public virtual string Password { get; set; }
[Property("ENABLED")]
public virtual string Enabled { get; set; }
[Property("SUPER_USER")]
public virtual string SuperUser { get; set; }
[Property("EMAIL")]
public virtual string Email { get; set; }
[Property("LAST_ACCESS")]
public virtual DateTime? LastAccess { get; set; }
[Property("PREVIOUS_LOGIN")]
public virtual DateTime? PreviousLogin { get; set; }
[Property("FIRST_NAME")]
public virtual string FirstName { get; set; }
[Property("LAST_NAME")]
public virtual string LastName { get; set; }
[Property("CONTACT_INFO")]
public virtual string ContactInfo { get; set; }
[Property("CULTURE")]
public virtual string Culture { get; set; }
}
我们正在使用延迟加载,表在用户名列上有索引。我已经使用SQL Server Profiler检查了所有内容,并且查询NHibernate在数据库上执行的操作几乎立即返回。
NHibernate生成查询:
exec sp_executesql N'SELECT TOP (@p0) this_.USER_ID as USER1_40_0_, this_.USER_NAME as USER2_40_0_, this_.PASSWORD as PASSWORD40_0_, this_.ENABLED as ENABLED40_0_, this_.SUPER_USER as SUPER5_40_0_, this_.EMAIL as EMAIL40_0_, this_.LAST_ACCESS as LAST7_40_0_, this_.PREVIOUS_LOGIN as PREVIOUS8_40_0_, this_.FIRST_NAME as FIRST9_40_0_, this_.LAST_NAME as LAST10_40_0_, this_.CONTACT_INFO as CONTACT11_40_0_, this_.CULTURE as CULTURE40_0_, this_.COMPANY_ID as COMPANY13_40_0_ FROM [USER] this_ WHERE this_.USER_NAME = @p1;', N'@p0 int, @p1 varchar(100)', @p0 = 2, @p1 = N'username'
在应用程序启动时(仅)创建SessionFactory。每次请求都会创建NHibernate会话。
在第二次调用时,相同的查询在大约30ms内执行。
任何人都可以解释第一次这么长时间拍摄的内容吗?
更新1
应用程序池配置为自动启动。当应用程序池回收时,我们也会调用预热脚本。
在对各种情况进行额外测试并公开应用程序后,我们发现了同样的问题,如果Web应用程序处于一小时或两小时不活动状态。