所以我已經用盡了爲什麼這是如此緩慢的想法。也許你可以幫忙。 所以我試圖做一個簡單的記錄從一個oracle數據庫使用nHibernate映射的代碼。我正在使用nuget的nHibernate verison 3.3.1.4。簡單得到使用NHibernate(使用映射代碼)是非常緩慢的
這裏是映射代碼:
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 coloumn被索引(它是表的主鍵)。
- 數據庫在服務器上,所以要檢查它是不是網絡吃飯的時間,我運行上面生成的查詢使用AD0.Net(Oracleconnection + Oraclecommand)。這大概需要180ms,這包括創建連接並將記錄映射到實體類。
- 通過PL/SQL開發人員進行查詢(花費大約32ms)。
- 檢查生成的查詢的查詢計劃(已確認使用索引掃描獨特的,而不是全表掃描)。
- 我已經在我的本地運行對一個類似規模的SQL2012分貝上面的代碼,並且它的快瘋了incomparison,圍繞180ms的通過NHibernate的代碼。
- 然nhprof(評估),並得到了以下結果:
好像運行查詢,結果被從數據庫(根據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'
),則執行快速(〜1ms),但如果其參數化(例如,select ... from person where personid = :p1
),那麼它很慢。由於我想利用nHibernate的力量,我需要使用生成的參數化查詢。我仍然試圖找出爲什麼甲骨文讀者
我想你不應該包括創建'SessionFactory'的時間。這很費時,但只需要一次,所以對於所有實際的目的,只檢查'using'語句的時間。 – Yogesh 2012-07-27 06:33:12
嗨,我沒有在底部包含一些代碼,但我已經分別測量了創建會話工廠以及session.get的時間。我所包含的數字僅僅反映了session.get。這段代碼只是一個POC,我清楚地知道使sessionfactory只應用一次。 – 2012-07-28 00:13:46
嘗試從第二次使用它時進行測量。 – 2012-07-28 20:09:02