2013-05-13 61 views
1
包含10000行

數據庫表(PostgreSQL的):NHibernate的 - 第一個查詢是痛苦的緩慢

CREATE TABLE test 
(
    id bigserial NOT NULL, 
    text text, 
    CONSTRAINT test_pkey PRIMARY KEY (id) 
) 

類:

public class Test 
{ 
    public virtual int ID { get; set; } 
    public virtual string Text { get; set; } 
} 

public class TestMap : ClassMap<Test> 
{ 
    public TestMap() 
    { 
     Table("test"); 
     Id(x => x.ID, "id"); 
     Map(x => x.Text, "text"); 
    } 
} 

這是我如何查詢數據庫:

using (ISession session = SessionBuilder.OpenSession()) 
{ 
    Stopwatch s = new Stopwatch(); 

    s.Start(); 
    var result = session.QueryOver<Test>().Where(test => test.Text == "aaa").List(); 
    s.Stop(); 
    Console.WriteLine(s.ElapsedMilliseconds); // >150ms 

    s.Restart(); 
    var result2 = session.QueryOver<Test>().Where(test => test.Text == "bbb").List(); 
    s.Stop(); 
    Console.WriteLine(s.ElapsedMilliseconds); // ~4ms 
} 

爲什麼第一個查詢需要很長時間?有沒有辦法加快速度?

+0

你需要做更多的挖掘。在PostgreSQL中啓用語句持續時間日誌並查看日誌,查看執行時間。查看nHibernate花費多少時間完成準備工作和元數據獲取,方法是在詳細瞭解之後檢查其日誌記錄。使用'explain analyze'來看看語句是如何執行的。等 – 2013-05-13 23:22:34

+0

你有沒有發現過什麼造成了你的滯後?我正在使用MS SQL Server作爲RDBMS遇到類似的問題。第一個查詢大約需要1000毫秒。查詢很簡單。通過用戶名從數據庫獲取用戶對象,並且表在用戶名列上具有索引。 – 2015-08-26 14:28:26

+0

@VladimirKocjancic是你的數據庫已經啓動並運行?因爲它可能只是數據庫的開始。 – TedOnTheNet 2015-10-01 22:31:45

回答

1

很可能被緩存。您沒有可以幫助查詢的索引,因此全表掃描是獲得答案的唯一方法。第一個將填充緩衝區和緩存,或者由DB(可能不會用於表掃描)填充緩存和緩存,但當然O/S會緩存全部或部分磁盤頁面。第二個查詢將受益於在某個級別緩存的頁面。

克雷格的建議也是一個微妙的旋轉緩存&啓動 - 你第一次做任何事情往往會招致一些打擊,你需要找出什麼。在Web應用程序中,您可以在應用程序接受請求之前做一些啓動操作。如果這更多的是批次的事情,你不能掩飾熱身,那麼你可能只需要忍受它或溝nHibernate。

請教他的建議&衡量Hibernate中發生了什麼。

1

在連接到數據庫時通常會有開銷,在這種情況下,由於連接池,您不會看到其他查詢。根據你在那裏的時間安排,我會說這是你所看到的問題。

此外,請確保您只會讓您的會話工廠只進行一次緩存,然後從中打開會話。我不認爲你會根據你的時間點進入,但是如果配置足夠小,那也可以。

0

可能的解決方案1:
幾年前我一直在看性能問題,我發現的問題是NHibernate使用的XML序列化程序的初始化。我已經在Jira上報告了一個錯誤和修復方法: https://nhibernate.jira.com/browse/NH-2958

嘗試修復您的nhibernate源文件並查看問題是否得到解決。根據jira系統,該問題將在下一版nhibernate中得到修復。

可能的解決方案2:
如果解決方案1不起作用,請嘗試在您的映射中爲每個類映射設置動態更新和動態插入爲true。 NHibernate在編譯映射時創建所有可能的查詢。