2

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

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

但:

  1. 数据库很大,网络很慢,所以每次查询都需要几秒钟。

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

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

  4. 为了调试,我们需要非常频繁地更改计算函数。

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

幸运的是,我们的数据每天只会更新一次,而且我们从数据库中获取的一些查询非常频繁地使用。

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

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

那么我可以memoize一天的结果,第二天自动更新结果吗?

谢谢您的帮助!

4

1 回答 1

7

您应该为此使用缓存,例如 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))))))
于 2016-10-27T15:23:07.107 回答