Глобальный runtime кеш AR моделей
Добавлено: 2013.09.23, 11:28
Задался таким вопросом, существует ли реализация рантайм кеша моделей, и если не существует, то почему бы её не внедрить.
Когда мы используем реляционные связи в ActiveRecord, иногда получается так, что выполняются лишние запросы, для уже ранее полученных моделей в пределах одного запроса страницы.
Например у меня есть модель новости (NewsModel), и модель комментарии (CommentsModel). У обоих из этих моделей, есть реляционная связь (BelongsTo), скажем CreateUser.
На странице я вывожу текст новости, под ней мета информацию, в т.ч. автора статьи ($news->createUser->name), затем идут комментарии, где возле каждого комментария выводится его автор ($comments->createUser->name).
К этой новости, кроме пользователей, оставляет комментарии так же и сам автор статьи.
Предположим по какой то причине я не захотел использовать with(), что бы выбрать всех комментаторов сразу с их комментариями (пример чисто синтетический). Получится что у нас будет 2 и более запроса к базе за одной и той же моделью автора новости. Первый раз когда мы покажем автора новости, и в следующий раз когда будем выводить его же комментарии.
Глобальный кеш предполагает что все модели, имеют некий идентификатор, например primaryKey, и при выполнении реляционного запроса система прежде проверяет нет ли уже в глобальном кеше такого id, и если есть, то возвращает оттуда.
Разумеется не все так просто. Иногда в реляционных запросах присутсвуют дополнительные параметры, поэтому в качестве id модели, можно использовать хеш от сериализованного объекта CdbCriteria.
Так же могут возникнуть плавающие глюки, связанные с тем что в рамках одного запроса страницы, мы можем сначала изменить модель, а затем её вывести. В таком случае лучше всего обнулять её в глобальном кеше сразу после сохранения изменений. Может показаться, что обнуление модели в кеше не обязательная процедура, т.к. все объекты передаются по ссылке и изменения сразу отобразятся и в кеше, но это не всегда так. Такой подход не сработает в случае если в качестве значения одного из свойств будет присвоено что ни будь типа new CdbExpression("NOW()").
В реальном проекте такой кеш может сократить количество ненужных запросов, которые очень сложно вынести на отдельный уровень абстракции и поможет избежать сквозного кода.
Когда мы используем реляционные связи в ActiveRecord, иногда получается так, что выполняются лишние запросы, для уже ранее полученных моделей в пределах одного запроса страницы.
Например у меня есть модель новости (NewsModel), и модель комментарии (CommentsModel). У обоих из этих моделей, есть реляционная связь (BelongsTo), скажем CreateUser.
На странице я вывожу текст новости, под ней мета информацию, в т.ч. автора статьи ($news->createUser->name), затем идут комментарии, где возле каждого комментария выводится его автор ($comments->createUser->name).
К этой новости, кроме пользователей, оставляет комментарии так же и сам автор статьи.
Предположим по какой то причине я не захотел использовать with(), что бы выбрать всех комментаторов сразу с их комментариями (пример чисто синтетический). Получится что у нас будет 2 и более запроса к базе за одной и той же моделью автора новости. Первый раз когда мы покажем автора новости, и в следующий раз когда будем выводить его же комментарии.
Глобальный кеш предполагает что все модели, имеют некий идентификатор, например primaryKey, и при выполнении реляционного запроса система прежде проверяет нет ли уже в глобальном кеше такого id, и если есть, то возвращает оттуда.
Разумеется не все так просто. Иногда в реляционных запросах присутсвуют дополнительные параметры, поэтому в качестве id модели, можно использовать хеш от сериализованного объекта CdbCriteria.
Так же могут возникнуть плавающие глюки, связанные с тем что в рамках одного запроса страницы, мы можем сначала изменить модель, а затем её вывести. В таком случае лучше всего обнулять её в глобальном кеше сразу после сохранения изменений. Может показаться, что обнуление модели в кеше не обязательная процедура, т.к. все объекты передаются по ссылке и изменения сразу отобразятся и в кеше, но это не всегда так. Такой подход не сработает в случае если в качестве значения одного из свойств будет присвоено что ни будь типа new CdbExpression("NOW()").
В реальном проекте такой кеш может сократить количество ненужных запросов, которые очень сложно вынести на отдельный уровень абстракции и поможет избежать сквозного кода.