2012-04-07 43 views
1

我有一個模型產品,它屬於一個類別(產品表中的category_id)。我想編寫一個查詢,其中包含類別名稱的前20個產品。我有2種方式獲取它的:哪一個是首選的::包括或:連接?

  1. 使用includes,像這樣:

    Product.includes(:category). 
         order(:updated_at). 
         limit(20) 
    

    ,並在這樣的意見,採取分類名稱:

    <%= product.category.name if product.category %> 
    

    這將創建一個查詢像這樣:

    SELECT `products`.* from `products` ORDER BY `products`.updated_at LIMIT 20 
    SELECT `categories`.* from `categories` WHERE `categories`.id IN (1,2,3,4,5..,25) 
    
  2. 使用joins這樣的:

    Product.joins("LEFT JOIN categories ON categories.id = products.category_id"). 
         select("products.*, categories.name as category_name"). 
         order(:updated_at). 
         limit(20) 
    

    ,並用它在意見是這樣的:

    <%= product.category_name %> 
    

    這會產生這樣的查詢:

    SELECT products.*, categories.name as category_name from `products` LEFT JOIN categories ON categories.id = products.category_id ORDER BY `products`.updated_at LIMIT 20 
    

方法1有我們可以使用類別模型上編寫的模型級方法,代碼爲m礦石可維護。但它的缺點是它使用單獨的查詢來查找使用IN子句的類別。

哪個是首選方式?

+2

還有方法3:Product.eager_load(:categories) – 2012-04-08 07:49:49

+0

@FrederickCheung ..我無法找到該方法的任何文檔。它有什麼作用? – rubyprince 2012-04-09 12:25:15

+0

與包含相同的效果(您可以獲得完整的類別實例),但可以使用基於聯接的查詢。 – 2012-04-09 13:20:27

回答

0

對於您的示例,我可能會使用選項1,因爲它更簡單,更易於閱讀,而且您不會加載那麼多的對象,所以我認爲性能不會太嚴重。在你可能會加載更多數據的情況下(例如,如果你脫掉了limit(20)部分),我會使用選項2,因爲它可以幫助你在需要的時候實例化類別對象,而不需要他們的名字。在較小的列表中,這種開銷可能可以忽略不計,但隨着列表變長,它可能變得重要。

0

首選方式是你個人喜歡的方式。

儘管如此,我並沒有看到使用includes這是一筆大交易。特別是在開發一款應用程序時,您在網頁上放置的內容將發生變化。

在我看來,在這種情況下大多數情況下只需要使用includes。除非你在行中存儲了很多text,否則你就會進入生產環境,而且這個查詢最終會成爲瓶頸,那麼你應該花點時間優化它。

2

它不僅僅是偏好,它是一個性能與可維護性的問題。我會首先爲您的查詢提供更易於維護的路線。如果您的性能開始受到某些查詢的影響,請使用連接語法進行優化,或者從頭開始編寫普通的舊sql。不要過早地優化。優化你發現實際需求的地方。

相關問題