[英]Why are my NHibernate queries so slow?
我正在使用Fluent NHibernate v2.0.50727到SQL Server后端構建ASP Web表單應用程序。
出於某種原因,查詢具有小數據(約14行)的表需要幾秒鍾。
映射都很簡單: Id(x => x.Id)
和Map(x => x.Name)
。 CertificateGroup還Map()的Color
和Rank
。
我已經隔離了用於測試的nhibernate代碼:(這不代表我的應用程序,但是針對SO進行了簡化和隔離)
protected void Page_Load(object sender, EventArgs e)
{
var config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("..."))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<PersonMap>()) .BuildConfiguration();
var factory = config.BuildSessionFactory();
using (var session = factory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var departments = session.QueryOver<DepartmentModel>().List(); // these all take seconds to execute - this has 14 results
var jobs = session.QueryOver<JobModel>().List(); // 113 results
var certificates = session.QueryOver<CertificateModel>().List(); //this one about 4 seconds for 210 results
var groups = session.QueryOver<CertificateGroupModel>().List();
var association = new CertificateAssociationModel
{
Department = departments.First(),
Job = jobs.First(),
Certificate = certificates.First(),
Group = groups.First()
};
session.SaveOrUpdate(association);
transaction.Commit();
}
}
}
我將nhibernate交換為實體框架,並運行了上面的代碼,並且獲取是即時的。
任何幫助表示贊賞。
編輯:
這是映射(如我上文所述):對於部門,職位和證書:
public class DepartmentMap : ClassMap<DepartmentModel>
{
public DepartmentMap()
{
Table("tblDepartment");
Id(x => x.Id);
Map(x => x.Name);
}
}
CertificateGroupModel
還具有Map(x => x.Rank);
Map(x => x.Color);
實體類都是相同的:
public class CertificateModel
{
public virtual Int32 Id { get; protected set; }
public virtual String Name { get; set; }
}
除了CertificateGroupModel之外,它還具有:
public virtual String Color { get; set; }
public virtual Int32 Rank { get; set; }
這是我的NHiberate分析器結果:
-- statement #1
begin transaction with isolation level: Unspecified
-- statement #2
SELECT this_.Id as Id4_0_,
this_.Name as Name4_0_
FROM tblDepartment this_
-- statement #3
SELECT this_.Id as Id5_0_,
this_.Type as Type5_0_
FROM tblJobTitles this_
-- statement #4
SELECT this_.Id as Id2_0_,
this_.Name as Name2_0_
FROM tblCertificate this_
-- statement #5
SELECT this_.Id as Id1_0_,
this_.Name as Name1_0_,
this_.Rank as Rank1_0_,
this_.Color as Color1_0_
FROM tbl_certificate_groups this_
-- statement #6
INSERT INTO lnk_certificate_associations
(Certificate_id,
Department_id,
Job_id,
Group_id)
VALUES (1 /* @p0 */,
1 /* @p1 */,
1 /* @p2 */,
1 /* @p3 */);
select SCOPE_IDENTITY()
-- statement #7
commit transaction
nhibprofile http://i.snag.gy/bTKHm.jpg
IL代碼生成:
var departments = session.QueryOver<DepartmentModel>().List();
IL_008F: ldloc.2 /* session */
IL_0090: callvirt instance NHibernate.IQueryOver`2<!!0, !!0> NHibernate.ISession::QueryOver<Core.Domain.Model.DepartmentModel>()
IL_0095: callvirt instance [mscorlib]System.Collections.Generic.IList`1<!0> NHibernate.IQueryOver`1<Core.Domain.Model.DepartmentModel>::List()
IL_009A: stloc.s departments
推測一下,由於您尚未在此處發布映射和表格...
您的數據庫中是否有任何可為空的列已映射為不可為空的類型(例如,可為null的int映射為模型中的int)?
這可能會引起您所看到的某種行為,因為當NHibernate加載您的實體時(假設上面的DepartmentModel場景,其屬性Prop1為int),如果Prop1在數據庫中為null,則該會話將具有一個內部狀態為null,但由於您無法將Prop1設置為null,因此將其分配為0,並且當會話檢查是否有任何更改時,它將看到Prop1已更改(從null變為0),並導致整體一堆更新,這反過來會減慢很多速度。
在這種情況下,解決方案是更新表定義或更新實體以具有正確的(可空)類型。
發生這種情況的方式有很多種,我只是舉了一個簡單的例子-如果您可以包括映射,表定義和實體類,這將很有幫助...
至於插入問題,如果您將身份生成器用於Id,則nHibernate首先會要求數據庫( INSERT...SELECT SCOPE_IDENTITY()
)為您的實體創建記錄,然后使用正確的ID和數據將其插入( UPDATE
)
請注意,對其他實體的引用將在UPDATE
因此您只會看到'?' 在插入
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.