2016-07-01 4 views
0

私は現在以下のモデルを持っています:MinorCategory> Product> Review ビューでは、最もレビューの少ない12 MinorCategoriesを表示します。このビューは非常に応答が遅く、クエリをどのように行うかは問題です。子どもの子供の数でモデルを並べ替える速やかな方法

class MinorCategory < ActiveRecord::Base 
    has_many :products 
    has_many :reviews, through: :products 
    ... 
    def count_reviews 
    self.reviews.count 
    end 
    ... 
end 

class Review < ActiveRecord::Base 
    belongs_to :product, touch: true 
    ... 
end 

class HomeController < ApplicationController 
    @categories = MinorCategory.all.sort_by(&:count_reviews).reverse.take(12) 
end 

だから、基本的にそれである:ここでは

は私の現在のコードです。ビュー自体では、各@categoriesを調べていくつかのことを表示しますが、コントローラのクエリは遅いと思われます。

SELECT COUNT(*)INNERは "レビュー" "product_idの" = "製品"、 "ID" WHERE "製品" "minor_category_id" ON "製品" を登録しよう "レビュー" FROM =:天窓から。。。? ... avg 472ms

私はSQLやアクティブなレコードではうまくいかず、Ruby on Railsではかなり新しいです。私は数時間かけて他の方法を試してみましたが、私はそれらを働かせることができないので、私はここでチェックすると思った。

あらかじめありがとうございます。

答えて

0

データベースクエリの仕組みやDBMSの活用方法を理解するためには、基本的なSQL知識が必要です。 ActiveRecordを使用することは、いくつかのSQLを習得しないという言い訳ではありません。

つまり、データベースのパワーをまったく使用しないため、クエリは非常に非効率的です。 Ruby環境とデータベース環境の両方でリソースが無駄になります。

のみデータベースクエリはすべてのレコードを抽出し

MinorCategory.all 

です。これは非常に高価です。特に、多数のカテゴリがある場合は非常に高価です。

さらに、self.reviews.countは、N+1 query issueの影響を受けるため、ほとんど効率が悪いです。

最後に、ソートと制限はRuby環境で行われますが、実際にはデータベースで行うべきです。

データベースの計算機能を利用すると、より効率的なクエリを簡単に取得できます。 2つのテーブルを結合する必要があります。クエリは次のようになります。

SELECT 
    minor_categories.*, COUNT(reviews.id) AS reviews_count 
FROM 
    "minor_categories" INNER JOIN "reviews" ON "reviews"."minor_category_id" = "minor_categories"."id" 
GROUP BY 
    minor_categories.id 
ORDER BY 
    reviews_count DESC 
LIMIT 10 

のActiveRecordに

categories = MinorCategory.select('minor_categories.*, COUNT(reviews.id) AS reviews_count').joins(:reviews).order('reviews_count DESC').group('minor_categories.id').limit(10) 

として変換されたあなたはreviews_count

# take a category 
category = categories[0] 
category.reviews_count 

に必要としない別のアプローチを使用して、単一のカテゴリ数をアクセスすることができますJOINは、カテゴリテーブルのカウンタをキャッシュすることです。

関連する問題