Кэширование в Rails позволяет повысить производительность вашего приложения.
В Rails 5 теперь можно кешировать коллекции записей, благодаря методу:
ActiveRecord::Relation#cache_key
Что из себя представляет кэширование коллекций
Рассмотрим пример, в котором нам нужно получить коллекцию пользователей с определенным именем.
1
|
|
В переменной @users
мы получим некую коллекцию записей, которая будет являться объектом класса ActiveRecord::Relation
Результат нашего запроса не изменится если будут выполнены следующие условия:
- Мы будем искать также
Михаила
- За время нашего запроса записи не были удалены
- За время нашего запроса не было добавлено новых записей
Rails комьюнити предложило реализовать кэширование для коллекций.
Метод cache_key
был добавлен в ActiveRecord::Relation
, и он учитывает множество факторов,
включая изменение запроса, updated_at
для запроса, и значение счетчика записей в коллекции.
ActiveRecord::Relation#cache_key
Итак у нас есть коллекция пользователей, давайте вызовем у этой коллекции метод cache_key
1 2 |
|
Мы получим вот такую запись. Сейчас подробнее рассмотрим что она означает.
users
представляет название коллекции, основанной на модели Userquery-
не меняющаяся часть, всегда будет присутствовать67sa32b36805c4b1ec1948b4eef8d58f
md5 сумма, котрая образуется из SQL. В нашем примере этоMD5("SELECT "users".* FROM "users" WHERE "users"."name" = 'Михаил'")
3
размер коллекции20160116111659084027
временная метка(timestamp). Это значение соответствует самому свежему updated_at в коллекции.
Как использовать?
Один из примеров, как можно применить cache_key
1 2 3 4 5 6 7 |
|
В модели нет колонки :updated_at
. Что делать?
По умолчанию, для создания timestamp, cache_key
использует колонку :updated_at
Это дефолтная реализация. Если у вас этой колонки нет, но есть другая, с названием отличным от стандартного, вы можете
использовать ee, указав как аргумент в вызове метода cache_key
1 2 3 |
|
Особенности использования
Использование limit в запросах
Рассмотрим 2 варианта.
Если мы хотим получить 3
пользователя с именем ‘Михаил’, то cache_key
корректно работает.
1 2 3 |
|
Но если мы вызовем cache_key
не извлекая записи в @users
, то получим следующую картину.
1 2 |
|
В итоге мы получаем всех пользователей, и наш limit
не учитывается. Это особенность реализации метода.
ActiveRecord::Base#collection_cache_key.
Cache_key
не меняется, при изменении порядка записей в коллекции
Например:
1 2 3 |
|
В итоге мы получаем пользователей с ids - [5, 4, 3]
Теперь попробуем удалить пользователя с id = 3
1 2 3 4 5 |
|
Обратите внимание, что cache_key
совпадают в обоих примерах.
Это происходит потому, что ни один из параметров, влияющих на ключ кэша не изменяется. Т.е. ни количество записей, ни запрос, ни метка времени последней записи.
Использование group
в запросах
Также как и в случае с limit
, cache_key
ведет себя по-разному, в случаях когда записи уже есть в памяти и когда их еще нет.
Допустим у нас есть несколько пользователей с одинаковыми именами:
1 2 |
|
В результате мы получаем размер записей 3
, в данном случае это будет количество записей в группе.
Теперь посмотрим что будет, если коллекция будет загружена в память
1 2 3 |
|
Теперь размер коллекции составляет 1
. Т.е кол-во групп.
Эти особенности нужно учитывать, иначе они могут сыграть злую шутку.