1

私の質問は概念的なものですが、私にとって非常に重要です。

データベースを使用する場合、通常、結果セットを含むクエリから反復子を取得します。ただし、ページングを行いたい場合は、その結果セットを前後に移動できるようにしたいと考えています。ただし、イテレータを使用してこれを行うことはできません。したがって、ここでの素朴なアイデアは、リストへの変換を使用することです。しかし、これにも O(n) の時間がかかり、パフォーマンスに関して深刻な問題を引き起こす可能性があります。

この問題には解決策があるはずです (elasticsearch :D を使用する以外に)。この問題にアプローチする最良の方法は何ですか?

敬具、

ステファン

4

1 に答える 1

1

O(n)ページングが必要ですが、ページングされていない結果セットをメモリにロードしたくない場合。当然のことですが、論理的には、データベースがページ化されたチャンクを渡さなければならないことを意味します。ほとんどの RDMS データベースには、「LIMIT」や「OFFSET」SQL のようなものがあると思います。

select id, name from foo where date > ? LIMIT $start, $page_size;

もしあなたが MySQL を扱っていて生の SQL を書いていたとしたら、それはそのようなものでしょう。しかし、Slick などのライブラリを使用すると、

val query = for { 
  d <- Parameter[Date]
  f <- foo if f.date > d
} yield (f.id, f.name)

したがって、すべての行を非ページ化するには、次のようにします

query(yesterday).list
// Select id, name from foo

ページングが必要な場合は、次のように簡単です。

query(yesterday).drop(20).take(5).list
// Select id, name from foo limit 20, 5 ; %% whatever; I suck at SQL and can't remember syntac

                                          %% but you get the point.

(Id, Name)ページごとに5つだけが必要だと仮定すると、5つの要素のリストが返されます。つまり、このサブシーケンスは結果の 5 ページ目になります。

これは、メモリ内に結果の代わりにある場合に行う可能性が高いことではありませんquery(yesterday)。SLICKは、コレクションで通常見られる多くの便利なメソッドを含む型であるListクエリの抽象化を提供します。メソッドは実際に最終的なクエリを実行して(このQuery例ではあなたのためにページングし、SLICKはそのSQLを生成するので、あなたはただやるだけです..listList[T]List[(Int, String)].takedrop.take.drop

モデル レイヤーが SLICK のコンポーザビリティを利用すると役立ちます。生の SQL を記述する代わりに SLICK で基本的なクエリを定義すると、これらのクエリは他のクエリのビルディング ブロックとして使用できます。

于 2013-10-16T18:08:05.530 に答える