2

更新開始

この問題は、SQlクエリではなく、各プロジェクトのフォームのレンダリングにありました。最適化するために、必要に応じてjavascriptを使用してフォームを追加します。

ミニプロファイラーのログを正しく読んでいないようです。申し訳ありませんが、同様の質問があるかもしれない他の人に質問を残してください。

更新終了

ミニプロファイラーを使用して、アプリのボトルネックを見つけています。そして、私はそれを見つけました!

SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON 
"projects"."id" = "memberships"."project_id" WHERE 
"memberships"."user_id" = 1 AND (active = 't')   
1059.50 ms  
Rendering: projects/_index — 1023.18 ms

1秒間に185のプロジェクトが見つかります。

これをより効率的に行うクエリを作成するにはどうすればよいですか?

これはprojects_controllerインデックスにあります

@projects = current_user.projects.is_active

プロジェクトモデルのis_activeスコープ

scope :is_active, where(["active = ?", true])

プロジェクトとユーザーは、メンバーシップ参加テーブルと多対多の関係を持っています

メンバーシップモデル

class Membership < ActiveRecord::Base
  attr_accessible :project_id,:user_id,:created_at,:updated_at
  belongs_to :user
  belongs_to :project
end

メンバーシップテーブル

def self.up
    create_table :memberships do |t|
      t.integer :project_id
      t.integer :user_id

      t.timestamps
    end
    add_index :memberships, [:project_id, :user_id], :unique => true
end

私はこれをデータベースとしてpostgreSQLを使用してローカルコンピューターの実稼働環境で実行しています

JiříPospíšilリクエストによる説明を追加します。コンソールでは、それはまったく遅いようには見えません。この説明は開発中に行われます。そこに同じ問題があります

User.first.projects.is_active.explain
  User Load (0.3ms)  SELECT "users".* FROM "users" LIMIT 1
  Project Load (2.3ms)  SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON "projects"."id" = "memberships"."project_id" WHERE "memberships"."user_id" = 1 AND (active = 't')
  EXPLAIN (0.2ms)  EXPLAIN QUERY PLAN SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON "projects"."id" = "memberships"."project_id" WHERE "memberships"."user_id" = 1 AND (active = 't')
 => "EXPLAIN for: SELECT \"projects\".* FROM \"projects\" INNER JOIN \"memberships\" ON \"projects\".\"id\" = \"memberships\".\"project_id\" WHERE \"memberships\".\"user_id\" = 1 AND (active = 't')\n0|0|1|SEARCH TABLE memberships USING INDEX index_memberships_on_user_id (user_id=?) (~10 rows)\n0|1|0|SEARCH TABLE projects USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)\n" 

景色

<% @projects.each do |project| %>
<li class="tab_list" id="project_<%= project.id.to_s %>"> 
  <div class="tab_list_text"><%= link_to project.name, project_path(project) %></div>
  <span class='open_project_update button edit' id="project_update" data-id="<%= project.id %>" data-object="project" title="Edit project">Edit</span> 
  <div class="dialog_form" id="project_update_<%= project.id %>_form" title="Update project" style="display:none;">
      <%= form_for(project) do |f| %>
      <ul>
      <li><%= f.label :name %><%= f.text_field :name %></li>
      <li><%= f.label :description %><%= f.text_field :description %></li>
      <li><%= f.label :due %><%= f.text_field :due, :value => project.due.strftime("%Y-%m-%d"), :id => "date_project_#{project.id}"  %></li>
      <li><%= f.label :customer_id %><%= f.select(:customer_id, @customers.map {|customer| [customer.name, customer.id]}, {:include_blank => 'None'})%></li>
      <li><%= f.submit 'Save', :class => 'submit' %></li></ul>
      <% end %>
  </div>
  <a class="activate_project button" data-object="project" data-id="<%= project.id.to_s %>">Archive</a>
</li>
<% end %>
4

3 に答える 3

6

プロジェクトの負荷は2.3msしかかかりません。projects/_indexをレンダリングする時間は1秒です。クエリはあなたのボトルネックではありません。

あなたのコメントに基づいて、あなたはあなたが関係をロードするのが怠惰であると言います。を使用して、関係を熱心にロードするようにしてくださいincludes

例えば:

@user.projects.is_active.includes(:some_association).includes(:another_association)

includes関係が熱心にロードされるようになります。

ユーザーのリストを繰り返し処理している場合、アクティブなプロジェクトを取得するには、次のような操作を行う必要があります。

User.includes(:projects)
     .merge(Project.is_active)
     .includes(projects: :some_other_association)

ビューにDBクエリを配置しないことをお勧めします。コントローラを介してそれを実行してみてください。

于 2012-12-14T13:24:23.833 に答える
1

これで、新しくリリースされたgem'query_optimizer'を使用できます 。query_optimizerは、has_manyおよびbelongs_toリレーションシップ2テーブルのレール内のクエリを最適化するための最良のgemです。

于 2015-10-21T08:07:19.203 に答える
0

まだ誰も言及していないので、弾丸の宝石は、熱心な読み込みincludes受け入れられた回答でよく概説されているものを使用)の恩恵を受ける可能性のあるN + 1クエリ(特定のケース)を誤って作成したアプリのページを識別するのに最適です。カウンターキャッシング

このすばらしい投稿では、問題と解決策の両方をシンプルで明確な言葉で概説し、弾丸の宝石の使用方法を紹介しています。私はそれを経験していませんが、弾丸の実装に関するRailsCastもあります。

于 2016-01-08T22:01:16.740 に答える