оптимальный формат запроса activerecord для числа X

#ruby-on-rails #caching #optimization #query-optimization

#ruby-on-rails #кэширование #оптимизация #оптимизация запросов

Вопрос:

Если, например, a Tweet has_many :favorites , быстрее ли вызывать Tweet.favorites.size или иметь отдельный атрибут / столбец в базе данных для Tweet такого, как num_of_favs . Хотя я изначально думал, что Tweet.favorites.size это быстрее, я знаю, что некоторые методы оптимизации Rails подробно описывают создание ваших собственных методов counter_cache, таких как Tweet модель, имеющая favorites_size атрибут, который не сильно отличается от num_of_favs . Я использую Postgres btw.

Комментарии:

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

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

3. @pixelearth итак, вы бы сказали, что это зависит от размера базы данных записей, из которых вы извлекаете? Например, если на моем сайте всего 50 твитов, это не имеет большого значения, но если бы это было 1000, это могло бы иметь большое значение?

4. Написал полный ответ…

Ответ №1:

Я выполнил следующие консольные тесты на некоторых из моих баз данных. У одного есть почти 60 000 строк. Конечно, это ни в коем случае не огромно.

Мои тесты показывают, что подсчет строк этой таблицы в 30 раз медленнее, чем извлечение значения из строки. Но когда вы говорите о .4ms или 12ms, лично для меня это не стоит оптимизации для моих проектов. Последний находится в ассоциации. Вы можете видеть время, за которым следует ms.

 Loading development environment (Rails 4.0.1)
Loading ~/.railsrc
2.0.0-p247 :001 > Log.count
   (12.3ms)  SELECT COUNT(*) FROM `logs`
58133
 

и

 2.0.0-p247 :002 > Log.first.method
  Log Load (0.4ms)  SELECT `logs`.* FROM `logs` ORDER BY `logs`.`id` ASC LIMIT 1
"GET"
2.0.0-p247 :003 > 
 

и

 1.8.7-p352 :005 > Pack.last.lessons.count
  Pack Load (0.6ms)  SELECT `packs`.* FROM `packs` ORDER BY packs.id DESC LIMIT 1
  SQL (2.8ms)  SELECT COUNT(*) FROM `lessons` INNER JOIN `lessons_packs` ON `lessons`.id = `lessons_packs`.lesson_id WHERE ((`lessons_packs`.pack_id = 460))
 => 103