所以我对为什么这么慢已经没有想法了。也许你可以帮忙。因此,我正在尝试使用 nHibernate 通过代码映射从 oracle db 中进行简单的记录。我正在使用来自 nuget 的 nHibernate 版本 3.3.1.4。
这是映射代码:
public class Person
{
public virtual PersonKey Key { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public class PersonKey
{
public virtual string PersonId { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as PersonKey;
if (t == null)
return false;
if (PersonId == t.PersonId)
return true;
return false;
}
public override int GetHashCode()
{
return (PersonId).GetHashCode();
}
}
public class PersonMap : ClassMapping<Person>
{
public PersonMap()
{
Schema("MyDB");
Table("Person");
ComponentAsId(id => id.Key, idMapper => idMapper.Property(p => p.PersonId));
Property(i => i.FirstName);
Property(i => i.LastName);
}
}
这是创建会话工厂和检索数据的代码。
var mapper = new ModelMapper();
var cfg = new Configuration();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
cfg.DataBaseIntegration(c =>
{
c.ConnectionString = @"User Id=user;Password=password;Data Source=MyDB;";
c.Driver<OracleClientDriver>();
c.Dialect<Oracle10gDialect>();
c.LogSqlInConsole = true;
c.LogFormattedSql = true;
c.AutoCommentSql = true;
});
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
var sessionFactory = cfg.BuildSessionFactory();
stopwatch.Stop();
Console.WriteLine("Building session factory: {0}", stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
Person entity = null;
using (var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction())
{
entity = (Person) session.Get("Person", new PersonKey(){PersonId = "1"});
tx.Commit();
}
生成的查询如下:
SELECT person0_.PersonId as PersonId0_0_,
person0_.FirstName as FirstName0_0_, person0_.LastName as LastName0_0_,
FROM MyDB.Person person0_
WHERE person0_.PersonId=:p0;
:p0 = '1'
平均大约需要 80-100 秒才能访问检索到的对象。这也包括创建会话。
所以我寻找了一些明显的东西:
- personId 列被索引(它是表的主键)。
- 数据库在服务器上,所以要检查它不是网络占用时间,我使用 AD0.Net (Oracleconnection + Oraclecommand) 运行上述生成的查询。这大约需要 180 毫秒,包括创建连接并将记录映射到实体类。
- 通过 PL/SQL 开发人员运行查询(大约需要 32 毫秒)。
- 检查生成查询的查询计划(确认使用索引唯一扫描而不是全表扫描)。
- 我已经在我的本地上针对类似大小的 sql 2012 db 运行了上述代码,并且通过 NHibernate 代码大约 180 毫秒。
- 运行 nhprof(评估)并得到以下结果:
似乎查询已运行并且结果从数据库返回的速度非常快(根据 nhprof 结果),但可能是将查询的值水合到占用时间的实体中。我不知道可能会浪费时间!
我的下一步是将 nHibernate 源附加到解决方案并逐步完成它,但是工作中的下载访问是有限的(甚至是 github!)。到那时有什么想法吗?
干杯。
更新:所以我在我的项目中获得了 nHibernate 源代码并逐步完成了它。一切都在顺利进行,直到程序到达这段代码:
for (count = 0; count < maxRows && rs.Read(); count++)
执行会rs.Read()
消耗时间,其中 rs 是 oracle 数据读取器。这段代码在DoQuery
Loader.cs 文件的函数中。
奇怪的是,如果传入的查询是一个非参数化的动态查询(例如select ... from person where personid = '1'
),执行速度很快(~ 1 毫秒),但如果它是参数化的(例如select ... from person where personid = :p1
),那么它的速度就慢得离谱。由于我想利用 nHibernate 的强大功能,我需要使用生成的参数化查询。我仍在试图弄清楚为什么甲骨文阅读器