2015-11-26 3 views
6

У меня есть рубин на Rails 4 приложение, используя devise и с моделью пользователя и модель сделки.Как использовать Rails для индексирования и запроса таблицы соединений?

Я создаю таблицу user_deals для отношений has_many/has_many между пользователем и сделкой.

Здесь миграция

class CreateUserDeals < ActiveRecord::Migration 

    def change 
    create_table :user_deals do |t| 
     t.belongs_to :user 
     t.belongs_to :deal 
     t.integer   :nb_views 

     t.timestamps 
    end 
    end 
end 

Когда пользователь загрузить сделки (например, идентификатор сделки = 4), я использую метод, называемый show

controllers/deal.rb 
#for the view of the Deal page 
def show 
end 

В связи с этим идентификатором сделки = 4 страницы, мне нужно отобразить nb видов Devise's current_userвнутри страницы сделки, на которой пользователь в настоящее время находится на.

deal/show.html 

here is the nb of views of user: <% current_user.#{deal_id}.nb_views%> 

Позволяет сказать, что у меня есть 10M + user_deals строки, я хотел бы знать, если я должен использовать индекс

add_index :user_deals, :user_id 
add_index :user_deals, :deal_id 

или, может быть,

add_index(:deals, [:user_id, deal_id]) 

Действительно, в других ситуациях я бы сказал Да, но здесь я не знаю, как Rails работает за кулисами. Кажется, что Rails знает, что делать без меня, чтобы ускорить процесс ... как будто Rails загружает это представление, что SQL-запроса нет (например, «найти nb представлений WHERe user_id= x и deal_id= Y») .... потому что я использую только для current_user, который зарегистрировался (через devise's current_user) и для deal_id Rails знает, что мы находимся на самой странице этой сделки (показать страницу), поэтому я просто передаю ее как параметр.

Мне нужен индекс, чтобы ускорить его или нет?

+2

Rails не делать что-либо с самой индексации. База данных управляет индексами и рельсами только делегаты для их создания. Так что это зависит от вашей базы данных. Я бы рекомендовал вам создавать индексы для внешних ключей, потому что они часто соединяются с другими таблицами. На мой взгляд, вы всегда должны создавать индексы для внешних ключей. И для многоколоночных индексов я бы использовал индекс только в том случае, если у меня есть ассоциация «многие-многие» или мне нужно проверить уникальность в определенной области. – Tobias

ответ

2

Ваш вопрос об индексах является хорошим. Rails делает генерировать SQL *, чтобы сделать свою магию, поэтому применяются обычные правила для оптимизации баз данных.

Магия разработки распространяется только на current_user. Он извлекает их данные с помощью SQL-запроса, который эффективен, потому что пользовательская таблица, созданная при разработке, по умолчанию имеет полезные индексы. Но это не те индексы, которые вам понадобятся.

Во-первых, есть аккуратнее более идиоматических способ сделать то, что вы после

class CreateUserDeals < ActiveRecord::Migration 
    def change 
    create_join_table :users, :deals do |t| 
     t.integer :nb_views 
     t.index [:user_id, :deal_id] 
     t.index [:deal_id, :user_id] 
     t.timestamps 
    end 
    end 
end 

Вы заметите, что миграция включены два индекса. Если вы никогда не ожидаете создать представление для всех пользователей для данной сделки, вам не понадобится второй из этих индексов. Однако, поскольку @chiptuned говорит, что индексирование каждого внешнего ключа почти всегда является правильным вызовом. Индекс по целому классу стоит немного ресурсов для записи, но платит большую экономию при чтении. Это очень низкая стоимость защиты по умолчанию.

У вас будет лучшее время, и все станет более ясным, если вы поместите свои логические данные в контроллер. Кроме того, вы показываете сделку , поэтому она будет чувствовать себя правильно, чтобы сделать это, а не current_user центром вашей выборки данных.

Вы можете сделать этот запрос без использования ассоциации through, потому что вы можете сделать это, не касаясь таблицы пользователей. (Скорее всего, вам понадобится ассоциация through для других обстоятельств.) Только has_many :user_deals выполнит эту работу.

Чтобы лучше воспользоваться механизмом базы данных и сделать это в одном запросе контроллер может выглядеть следующим образом:

def show 
    @deal = Deal.includes(:user_deals) 
       .joins(:user_deals) 
       .where("User_deals.user_id = ?", current_user.id) 
       .find(params["deal_id"]) 
end 

Тогда на ваш взгляд ...

I can get info about the deal: <%= @deal.description %> 

And thanks to the `includes` I can get user nb_views without a separate SQL query: 
<%= @deal.user_deals.nb_views %> 

* Если вы хотите чтобы увидеть, какие SQL-рельсы магически генерируют, просто положив .to_sql на конец. например sql_string = current_user.deals.all.to_sql

+0

благодарит за этот подробный ответ – Mathieu

1

Да, вы должны использовать индекс, чтобы ускорить запрос записей user_deals. Определенно, по крайней мере, на user_id, но, вероятно, и [:user_id, :deal_id], как вы заявили.

А почему вы не видите запрос SQL ...

Во-первых, ваш код в представлении оказывается неверным. Предполагая, что вы создали has_many :deals, through: :user_deals ассоциацию на вашем User классе, это должно быть что-то вроде:

here is the nb of views of user: <%= current_user.deals.find(deal_id).nb_views %>

Если вы видите правильное число, показывающее на nb_views, то запрос должен быть сделан, когда представление оказывается если current_user.deals уже загружен ранее в процессе обработки или у вас есть какое-то кэширование.

Если Rails «осведомлен», есть какая-то причина, по которой вы должны это выяснить. Ожидаемое поведение Rails в режиме реального времени заключается в том, что там выдается SQL-запрос.

1

является экологически чистым способом индексации других таблиц: не

class CreateUserDeals < ActiveRecord::Migration 

    def change 
     create_table :user_deals do |t| 
     t.references :user 
     t.references :deal 
     t.integer :nb_views 

     t.timestamps 
     end 
    end 
end 
+0

Я верю, что 'принадлежит_то' и' ссылки' являются синонимами – Adamantish

+1

@Adamantish 'reference' также добавляет индекс для столбца в Rails 4, так что, как он отличается. Если автор идет с многоколоночным индексом, то они захотят использовать что-то ближе к своей миграции, чем это предлагалось. – chiptuned

+0

@chiptuned Ах, спасибо за обновление меня – Adamantish

Смежные вопросы