Clojure的`memoize`函数是否可用于缓存慢速sql查询和复杂计算?

cma*_*mal 1 caching clojure pure-function

我的项目有一个mysql数据库和一个由Clojure编写的后端.

一些数据库表每天只更新一次,以查询我们将使用的最新信息.

但:

  1. 数据库非常大,网络速度很慢,因此每个查询都需要几秒钟.

  2. 我们需要在每次查询后进行复杂的计算.

  3. 我们需要进行多种sql查询,因此保存每个sql查询的结果是不现实的.

  4. 我们需要经常更改计算函数以进行调试.

对于我们来说,在慢速sql查询的情况下,所有事情都太慢了.

幸运的是,我们的数据每天只会更新一次,并且我们经常使用来自数据库的一些查询.

所以我们要缓存常用的sql查询和中间结果.

Clojure的memoize功能对这类工作有用吗?我担心sql查询不纯,所以memoize不应该缓存他们的结果.但是有一天我们的SQL查询结果必须相同.

那么我可以memoize在一天内得到结果并在第二天自动更新结果吗?

谢谢您的帮助!

Sva*_*nte 6

您应该使用缓存,例如clojure.core.cache.

澄清注释:memoization有助于纯函数:如果你的函数总是在给定相同输入的情况下返回相同的输出,你可以在计算一次后存储它.

如果输出随时间变化,则需要进行无效.带有失效的记忆(以及一些其他问题,例如记忆事物的大小)称为"缓存".

如果使用memoization机制进行缓存,那么您实际执行的操作是在其上实现缓存.使用缓存库的工作要少得多.

在这种情况下,您需要实现类似"午夜失效"的内容.有关如何执行此操作的指示,请参阅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))))))
Run Code Online (Sandbox Code Playgroud)