Полезна ли функция «memoize» в Clojure для кэширования медленных SQL-запросов и сложных вычислений?

В моем проекте есть база данных mysql и серверная часть, написанная Clojure.

Некоторая таблица базы данных обновляется только один раз в день, чтобы запрашивать самую свежую информацию, которую мы будем использовать.

Но:

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

  2. нам нужно выполнять сложные вычисления после каждого запроса.

  3. нам нужно выполнять множество видов sql-запросов, поэтому сохранять результаты каждого sql-запроса нереально.

  4. нам нужно очень часто изменять вычислительные функции с целью отладки.

В случае медленных запросов sql все идет слишком медленно.

К счастью, наши данные будут обновляться только один раз в день, и что некоторые из наших запросов из базы данных используются очень часто.

Поэтому мы хотим кэшировать часто используемые запросы sql и промежуточные результаты.

Полезна ли функция Clojure memoize для такого рода работ? Я боюсь, что запросы sql не чисты, поэтому memoize не должны кэшировать их результаты. Но в течение одного дня результаты наших sql-запросов должны быть идентичны.

Итак, могу ли я memoize получить результаты в течение одного дня и автоматически обновлять результаты на следующий день?

Спасибо за помощь!


person cmal    schedule 27.10.2016    source источник


Ответы (1)


Для этого лучше использовать кеш, например. грамм. clojure.core.cache.

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

Если результат со временем меняется, вам нужно сделать недействительность. Мемоизация с аннулированием (и некоторыми другими проблемами, такими как размер запоминаемых вещей) называется «кешированием».

Если вы используете механизм мемоизации для кеширования, то на самом деле вы реализуете кеш поверх него. Гораздо меньше работы просто использовать кэширующую библиотеку.

В этом случае вам нужно будет реализовать что-то вроде «аннулирования в полночь». См. https://github.com/clojure/core.cache/wiki, чтобы узнать, как сделать это.

РЕДАКТИРОВАТЬ: Это может выглядеть примерно так (непроверено, принесите свой today):

(defcache MidnightCache [cache dates]
  CacheProtocol
  (lookup [this key]
    (lookup this key nil))
  (lookup [this key not-found]
    (if (has? this key)
      (get cache key)
      not-found))
  (has? [this key]
    (let [d (get dates key)]
      (and d
           (= d (today)))))
  (hit [this key]
    this)
  (miss [this key new-value]
    (MidnightCache. (assoc (dissoc cache key)
                           key new-value)
                    (assoc (dissoc dates key)
                           key (today))))
  (evict [this key]
    (MidnightCache. (dissoc cache key)
                    (dissoc dates key)))
  (seed [this base]
    (MidnightCache. base
                    (zipmap (keys base)
                            (iterate identity (today))))))
person Svante    schedule 27.10.2016
comment
Почему не clojure.core.memoize? - person Leon Grapenthin; 27.10.2016
comment
Спасибо за ваш код. Это просто элегантный способ, который мне действительно нужен для работы. - person cmal; 28.10.2016