Есть ли способ кеширования механизма для Class::DBI?

У меня есть набор довольно сложных модулей ORM, которые наследуются от Class::DBI. Поскольку данные изменяются довольно редко, я рассматриваю возможность использования слоя Caching/Memoization для ускорения процесса. Я нашел модуль: Class::DBI:: Cacheable, но нет рейтинга или каких-либо отзывов о RT. Я был бы признателен от людей, которые использовали эту или любую другую схему кэширования Class::DBI.

Благодаря тонну.

3 ответа

Решение

Я тоже катал свой собственный ORM много раз, что я ненавижу говорить! Кэширование / запоминание довольно легко, если все ваши выборки происходят через один API (или его подклассы).

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

my %_cache;

sub get_object_from_db {
    my ($self, $table, %table_lookup_key) = @_;

    # concatenate a unique key for this object
    my $cache_key = join('|', map { "$_|$table_lookup_key{$_}" }
                       sort keys %table_lookup_key

    return $_cache{$cache_key}
        if exists $_cache{$cache_key};

    # otherwise get the object from the db and cache it in the hash
    # before returning
}

Вместо хеша вы можете использовать набор модулей Cache:: на CPAN для реализации ограничений по времени и памяти в вашем кеше.

Если вы собираетесь кешировать какое-то время, возможно, вы захотите подумать о способе истечения срока действия объектов в кеше. Если, например, все ваши обновления также проходят через ORM, вы можете очистить (или обновить) запись кэша в вашем методе update() ORM.

Последний момент, о котором нужно тщательно подумать - вы возвращаете один и тот же объект каждый раз, что имеет значение. Если, например, один фрагмент кода извлекает объект и обновляет значение, но не фиксирует это изменение в БД, весь другой код, извлекающий этот объект, увидит это изменение. Это может быть очень полезно, если вы объединяете последовательность операций - все они могут обновить объект, а затем вы можете зафиксировать его в конце - но это может быть не тем, что вы намеревались. Я обычно устанавливаю флаг на объекте, когда он только что из базы данных, а затем в вашем методе setter аннулируем этот флаг, если объект обновляется - таким образом, вы всегда можете проверить этот флаг, если вы действительно хотите свежий объект.

Несколько раз мы катали свои собственные, но мы ограничивали его особыми случаями, когда профилирование указывало на необходимость повышения (например, крупные объединения). Поскольку наши приложения обычно используют пользовательский уровень абстракции (похожий на доморощенный ORM) поверх доступа к БД, именно здесь мы реализовали кэширование. Мы добились хороших результатов, которые нас устраивали, и это не потребовало много усилий. Конечно, поскольку мы не использовали CPAN ORM, у нас на самом деле не было и выбора в использовании модуля кэширования CPAN.

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

Я использовал memcached прежде, чтобы кэшировать объекты, но не с Class::DBI (ORM заставляет меня чувствовать себя грязным).

Другие вопросы по тегам