12

Если у вас есть приложение Rail с множеством сложных связанных моделей, какие методы вы используете для сокращения запросов к базе данных?Методы сокращения запросов к базе данных в приложении Rails

На самом деле, я продолжу этот вопрос немного дальше и спрошу, что вы считаете «слишком много» запросов для любой страницы?

У меня есть страница, которая, как я ожидаю, закончится попав в базу данных примерно в 20 раз за каждую загрузку на страницу. Это касается, но не знаю, должно ли это касаться меня, или что я могу сделать, чтобы уменьшить нагрузку?

ответ

14

Отъезд: bullet

Его отличный способ определить п + 1 запросов и предлагает предложения, чтобы минимизировать его.

Он замедляет режим разработки, поэтому обязательно отключите его, если вы не настроите настройку производительности.

В то время как мы на него, а также проверка: rails_indexes

Простой способ определить, какие индексы ваше приложение может отсутствовать.

Счастливый тюнинг.

+0

Как это фактически уменьшает загрузку базы данных? Кэш-память? –

-1

Действительно сложно оценить предел для запросов. Это связано с концепцией/дизайном вашего приложения.

Если вам не нужно перезагружать всю страницу, я предлагаю вам рассмотреть javascript (или rjs), чтобы обновлять только нужные вам данные. Это должно быть также улучшением пользовательского интерфейса, вашим пользователям это понравится!

Проверьте SQL, сгенерированный из запросов ActiveRecord. Будьте уверены, что все как ожидалось.

Рассмотрите возможность денормализации вашего db, чтобы улучшить производительность. (будьте осторожны)

Это то, что я вижу из «кодовой стороны».

10

Общей практикой является разумное использование опции include =>: association.

Например, на контроллере вы можете сделать:

def show 
    @items = Item.find(:all) 
end 

... и вид шоу будет делать что-то вроде:

<% @items.each |item| %> 
    <%= item.product.title %> 
<% end %> 

Это создаст запрос для каждого вызова продукта. Но если вы объявляете связь включена следующим образом, вы получаете нетерпеливо нагруженные ассоциации в одном запросе:

def show 
    @items = Item.find(:all, :include => :product) 
end 

Как всегда, проверьте консоль для запроса времени и тому подобное.

0

Я использую: объединяет и: выбирает параметры, если вам нужно просто отображать данные. Я нашел очень полезным named_scope, чтобы определить все возможные: объединения и одно: select_columns named_scope.Пример

class Activity < ActiveRecord::Base 
     belongs_to :event 
     belongs_to :html_template 
     has_many :participants 

     named_scope :join_event, :joins => :event 
     named_scope :join_owner, :joins => {:event => :owner} 
     named_scope :left_join_html_template, 
     :joins => "LEFT JOIN html_templates ON html_templates.id = activities.html_template_id" 
     named_scope :select_columns, lambda { |columns| {:select => columns}} 
     named_scope :order, lambda{ |order| {:order => order}} 
end 

Итак, теперь вы можете Исли строить запросы, как это:

columns = "activities.*,events.title,events.owner_id,owners.full_name as owner_name" 
@activities = Activity.join_event.join_owner.order("date_from ASC").select_columns(columns) 

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