2017-11-19 16 views
2

私は仮説的な状況を解決したいと思いますが、理想的な答えは見つかりません。クエリから返される巨大なデータセットがあるとします。メモリへの影響が最小限になるようにページをどのようにペーニングしますか? datoms APIは、データを繰り返し処理し、1つずつフィルタリングしますか? index-range APIですが、datoms APIと同じことをしなければならないでしょう。 IDのみを返す初期クエリを実行し、それらのIDをページ分割して、別のクエリで使用してデータセット全体を取得できるようにします。Datomicでの照会結果のページ区切り

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 

答えて

5

など多くのことを考慮する必要があります。

最初に、Datomicに同梱されているDatalogの実装は熱心であり、ディスクに流出しないため、Datalogクエリの結果セットはメモリに収まる必要があります。

これは、各データログクエリでデータのわずかな部分のみを扱うことができるため、大きなデータ結果との互換性がないことを意味しません。たとえば、Datalogを使用してクエリの「論理」部分(返すエンティティ)とEntity APIまたはPull APIを使用して、クエリの 'content'部分を(遅延して)計算することができます各エンティティごとに)。 Entity IdがちょうどJava Long(8バイト)であることを考えると、これは2つの大きさのメモリフットプリントのうちの1つを節約できます。あなたが熱心に二次ブロブストアに結果全体を格納することによって、このアプローチを補完して、ページネーションのためにそれに対してポーリングすることができ

(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])))) 
    )) 

:エンティティのAPIを使用して実施例。

クエリロジックが複雑すぎない場合は、Datalogをまったく使用しないことも考えられます(たとえば、Datoms APIやIndex Range APIなどのローインデックスアクセスを使用するなど)。

最後に、Datomicが分析クエリのサービスに適していない可能性があることを考慮する必要があります。変更検出はDatomicでは簡単ではないので、解析クエリ(ElasticSearch、Google BigQuery、PostgreSQLなど)を計算するのに適したセカンダリストアに派生データをストリームするのはかなり簡単です

0

は、あなたがこのページを見たことがあります:あなたは通常、クエリ自体に改ページを定義することができますSQLで

http://docs.datomic.com/query.html#memory-usage

すべての中間結果がメモリに収まらなければならないことを言っているようです。私はこれが最終結果にも当てはまると仮定します。

あなたがでオーバー尋ねてみてください:https://forum.datomic.com/


サイドノート:Datomic戻り、エンティティ、それが明示的に完全には表示されません、それは、コンクリートになり、「怠惰マップ」の形式であります

(let [plain-map (into {} entity-map) ] 
    (println plain-map)) 
+1

また、(datomic.api/REPLでエンティティを検査するために 'my-entityに触れる ')。 'into 'との違いは、' touch'がプレーンなClojureマップではなく、(人口になった)エンティティを返すことです。 –

関連する問題