#database #ruby-on-rails-3 #arel
#База данных #ruby-on-rails-3 #arel
Вопрос:
Итак, я хотел бы знать, какой из следующих способов более эффективен. На самом деле лучшим ответом было бы спросить, как я могу понять это для себя в будущем.
Два запроса:
# id integer
# created_at datetime
# collection_id integer
# updated_at datetime
class Post < ActiveRecord::Base
belongs_to :collection
end
Post.where(:collection_id => collection_id).order(:updated_at).last
против
Post.where(:collection_id => collection_id).order("updated_at DESC").first
Итак, вопрос из 2 частей:
1) какое из этих утверждений более эффективно? (Если у меня нет опечатки, они должны быть эквивалентны)
2) как я мог бы ответить на этот вопрос для себя?
Я предполагаю, что никаких индексов нет. Мне также любопытно узнать, меняется ли ответ в зависимости от ожидаемого размера результирующего набора части запроса by collect_id .
Ответ №1:
По крайней мере, в Rails 3.1 оба ваших запроса фактически будут выполнять один и тот же запрос к базе данных. Rails достаточно умен, чтобы знать, что вызов .last
запроса должен просто изменить порядок и вместо этого ограничить его одним запросом. Таким образом, строка ниже на самом деле просто добавится ORDER BY updated_at DESC LIMIT 1
в конец вашего запроса. Другими словами, эта строка не возвращает все записи из базы данных, создает объекты ActiveRecord для каждой из них, а затем возвращает последний, что было бы гораздо менее эффективно.
Post.where(:collection_id => collection_id).order(:updated_at).last
Ответ №2:
Если вы посмотрите на консоль, вы увидите (1), какой запрос (или запросы) фактически выполняется, и (2) время, которое потребовалось для выполнения. Это был бы основной способ отслеживания эффективности.
В производстве также есть такие инструменты, как NewRelic RPM, которые будут выдавать вам предупреждения / анализ скорости / времени выполнения запросов. Я думаю, что бесплатная версия будет проводить анализ эффективности, но сохраняет записи только за предыдущие 30 минут выполнения приложения.
Как правило (но не строго говоря), чем меньше количество отправляемых вами запросов, тем лучше, отчасти потому, что это требует меньшего количества обходов между Rails и БД.
Если вы хотите что-то, что также бесплатно и, возможно, более повторяемо, то вы можете добавить несколько тестов производительности, в которых вы выполняете запросы снова и снова, синхронизируя их с каждым запуском и просто убедившись, что время выполнения действия запроса / контроллера меньше, чем какой-либо выбранный вами эталон, или чтосреднее время выполнения нескольких исполнений ниже некоторого порога.
Этот метод также можно использовать в качестве средства наблюдения за действиями, которые чаще всего попадают в ваше приложение, и завершаются неудачей, если они занимают больше времени, чем ожидалось. Конечно, тест будет охватывать только моделируемую среду, его можно использовать как общее указание на то, полностью ли критические действия выходят за рамки ожидаемой производительности.