Методы сокращения запросов к базе данных в приложении Rails

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

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

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

4 ответов


Проверьте: пуля

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

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

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

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

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


одной из распространенных практик является разумное использование опции 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

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


Я использованияконтактная :соединения и выберите Параметры, Если вам нужно просто отобразить данные. Я нашел очень полезный named_scope для определения всех возможных: joins и one: 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)

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


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

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

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

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

Это то, что я вижу от "кода".