gpt4 book ai didi

c# - 使用 NHibernate 的简单获取(使用按代码映射)非常慢

转载 作者:搜寻专家 更新时间:2023-10-30 19:51:30 25 4
gpt4 key购买 nike

所以我想不出为什么这么慢。也许你能帮忙。所以我试图通过代码使用 nHibernate 映射从 oracle 数据库中进行简单的记录。我正在使用来自 nuget 的 nHibernate verison 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);
}
}

下面是创建 session 工厂和检索数据的代码。

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 秒。这也包括创建 session 。

所以我寻找了一些明显的东西:

  • personId 列已编入索引(它是表的主键)。
  • 数据库在服务器上,所以为了检查它是不是网络占用了时间,我使用 AD0.Net (Oracleconnection + Oraclecommand) 运行了上面生成的查询。这大约需要 180 毫秒,包括创建连接和将记录映射到实体类。
  • 通过 PL/SQL 开发人员运行查询(耗时约 32 毫秒)。
  • 检查生成的查询的查询计划(确认使用索引唯一扫描而不是全表扫描)。
  • 我已经在本地针对类似大小的 sql 2012 数据库运行了上述代码,通过 NHibernate 代码,它的速度非常快,大约 180 毫秒。
  • 运行 nhprof(评估)并获得以下结果:

Results from NHibernate profiler

似乎查询已运行并且结果从数据库中返回的速度非常快(根据 nhprof 结果),但可能是查询值与实体的结合占用了时间。我不知所措,可能会浪费时间!

我的下一步是将 nHibernate 源附加到解决方案并逐步完成它,但工作中的下载访问是有限的(甚至是 github!)。到那时有什么想法吗?

干杯。

更新:所以我在我的项目中获得了 nHibernate 源代码并逐步完成了它。一切都进展顺利,直到程序到达这段代码:

for (count = 0; count < maxRows && rs.Read(); count++)              

正是在 rs.Read() 上,执行耗尽了时间,其中 rs 是 oracle datareader。这段代码在Loader.cs文件中的DoQuery函数中。

奇怪的是,如果传入的查询是非参数化动态查询(例如,select ... from person where personid = '1'),执行速度非常快(~ 1 毫秒) ),但如果它的参数化(例如 select ... from person where personid = :p1),那么它会慢得离谱。由于我想利用 nHibernate 的强大功能,我需要使用生成的参数化查询。我还在试图弄清楚为什么 oracle 阅读器

最佳答案

在博客中找到问题和解决方案 here作者 Deep Shah。

本质上,NHibernate 中带有 Oracle 的 Microsoft 驱动程序的参数化查询是造成瓶颈的原因。

他接着分享了两个解决方案:

  1. 将当前的 Microsoft oracle 驱动程序替换为 oracle 开发的 Oracle 数据客户端驱动程序。使用新的驱动程序运行相同的查询消除了性能瓶颈。为此,您需要在要触发查询的计算机上安装 Oracle 数据访问组件 (ODAC)。

  2. 在通过 NHibernate 为查询设置参数时,在查询 VARCHAR 列时使用“query.SetAnsiString”而不是“query.SetParameter”。

我已经验证了这两种解决方案,它们都有效。解决方案一是我采用的解决方案,因为我使用的是按代码映射,并且我将查询生成留给 nHibernate。

关于c# - 使用 NHibernate 的简单获取(使用按代码映射)非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11680311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com