当前位置:  开发笔记 > 编程语言 > 正文

在Datomic中查询结果分页

如何解决《在Datomic中查询结果分页》经验,为你挑选了1个好方法。

我有一个我想解决的假设情况,但我找不到理想的答案.假设您有一个可以从查询返回的庞大数据集,您如何对其进行分页以使对内存的影响最小化?该datoms API,遍历datoms和过滤逐一?该指数范围API,但我会做同样的事情datoms API中,遍历项目和过滤逐一?执行一个只返回id的初始查询,并对这些id进行分页,以便它们可以在另一个查询中用于检索整个数据集?

在SQL中,您通常可以在查询本身中定义分页:

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Valentin Wae.. 6

有很多事情需要考虑.

首先,在撰写本文时,Datomic附带的Datalog实现非常渴望,并且不会溢出到磁盘,这意味着Datalog查询的结果集必须适合内存.

这并不意味着Datalog与大结果不兼容,因为您可以让每个Datalog查询仅处理一小部分数据.例如,您可以使用Datalog计算查询的"逻辑"部分(要返回的实体),以及Entity API或Pull API(懒惰地)计算查询的"内容"部分(返回哪些属性)对于每个实体).鉴于Entity Id只是一个Java Long(8字节),这可以为您节省两个数量级的内存占用量.使用Entity API的示例:

(defn export-customers 
  [db search-criteria]
  (->> 
    ;; logical part - Datalog-based, eager
    (d/q '[:find [?customer ...] :in % $ ?search-criteria :where
           (customer-matches-criteria ?search-criteria ?customer)]
      (my-rules) db search-criteria)
    ;; content part - Entity API based, lazy
    (map (fn [eid]
           (let [customer (d/entity db eid)]
             (select-keys customer 
               [:customer/id 
                :customer/email
                :customer/firstName
                :customer/lastName
                :customer/subscription-time]))))
    ))

您可以通过热切地将整个结果存储在辅助blob存储中来补充此方法,然后针对该分页进行轮询.

如果您的查询逻辑不是太复杂,您也可以想象根本不使用Datalog,例如通过使用原始索引访问(例如,使用Datoms API或Index Range API).

最后,您应该考虑到Datomic不适合为您的分析查询提供服务.因为使用Datomic进行变更检测是微不足道的,所以很容易将派生数据流式传输到辅助存储,这些辅助存储将更好地用于计算分析查询(例如ElasticSearch,Google BigQuery,PostgreSQL等)



1> Valentin Wae..:

有很多事情需要考虑.

首先,在撰写本文时,Datomic附带的Datalog实现非常渴望,并且不会溢出到磁盘,这意味着Datalog查询的结果集必须适合内存.

这并不意味着Datalog与大结果不兼容,因为您可以让每个Datalog查询仅处理一小部分数据.例如,您可以使用Datalog计算查询的"逻辑"部分(要返回的实体),以及Entity API或Pull API(懒惰地)计算查询的"内容"部分(返回哪些属性)对于每个实体).鉴于Entity Id只是一个Java Long(8字节),这可以为您节省两个数量级的内存占用量.使用Entity API的示例:

(defn export-customers 
  [db search-criteria]
  (->> 
    ;; logical part - Datalog-based, eager
    (d/q '[:find [?customer ...] :in % $ ?search-criteria :where
           (customer-matches-criteria ?search-criteria ?customer)]
      (my-rules) db search-criteria)
    ;; content part - Entity API based, lazy
    (map (fn [eid]
           (let [customer (d/entity db eid)]
             (select-keys customer 
               [:customer/id 
                :customer/email
                :customer/firstName
                :customer/lastName
                :customer/subscription-time]))))
    ))

您可以通过热切地将整个结果存储在辅助blob存储中来补充此方法,然后针对该分页进行轮询.

如果您的查询逻辑不是太复杂,您也可以想象根本不使用Datalog,例如通过使用原始索引访问(例如,使用Datoms API或Index Range API).

最后,您应该考虑到Datomic不适合为您的分析查询提供服务.因为使用Datomic进行变更检测是微不足道的,所以很容易将派生数据流式传输到辅助存储,这些辅助存储将更好地用于计算分析查询(例如ElasticSearch,Google BigQuery,PostgreSQL等)

推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有