2013-11-05 73 views
1

我有一個Grails應用程序,它執行的是一個相當大的createCriteria查詢從多個表中拉取。我注意到性能非常糟糕,並且已經將它指向了我之後做的對象操作,而不是createCriteria本身。我的查詢成功獲取了我想要的所有原始對象,但是當我操作對象時,它正在爲每個元素執行一個新的查詢。這裏是我的控制器代碼的簡化版本:使用連接提高Grails的CreateCriteria查詢速度

def hosts = Host.createCriteria().list(max: maxRows, offset: rowOffset) { 
    // Lots of if statements for filters, etc. 
} 

def results = hosts?.collect{ [ cell: [ 
    it.hostname, 
    it.type, 
    it.status.toString(), 
    it.env.toString(), 
    it.supporter.person.toString() 
    ... 
]]} 

我有更多的領域,包括調用執行他們自己的查詢找到相關對象的方法。所以我的問題是:如何將連接加入到原始查詢中,以便我不對每個單獨的行執行大量額外的查詢?目前查詢〜700行需要2分鐘,這太長了。任何建議都會很棒!謝謝!

回答

3

您使用條件的一個好處是您可以輕鬆獲取關聯eagerly。因此,在引用關聯時,您不會遇到衆所周知的N + 1問題。

您沒有在標準中提到的邏輯,但我會建議爲〜700行,我肯定會去的東西是這樣的:

def hosts = Host.createCriteria().list(max: maxRows, offset: rowOffset) { 
    ... 
    //associations are eagerly fetched if a DSL like below 
    //is used in Criteria query 
    supporter{ 
     person{ 

     } 
    } 

    someOtherAssoc{ 
     //Involve logic if required 
     //eq('someOtherProperty', someOtherValue) 
    } 
} 

如果你覺得剪裁的標準很麻煩,那麼你就可以很回退到HQL,並使用join fetch進行關聯索引。

我希望這肯定會將約700秒的記錄週轉時間縮短到5秒以內。

+1

我注意到這種方法不適用於可空字段。例如,如果「支持者」字段爲空,那麼查詢根本不會返回該行。有沒有辦法解決這個問題? – Nisrak

+1

是的。關聯使用'inner joins'默認熱切獲取,因此不能爲空。您可以強制它使用LEFT JOIN以獲得可爲空的字段。按照[這個其他答案](http://stackoverflow.com/a/19391255/2051952),你會得到語法。 @Nisrak – dmahapatro

+0

太棒了!非常感謝! – Nisrak