問題
大量のレコード (約 1000) を読み書きする必要があります。以下の例では、1000 レコードを書き込むのに 20 分もかかり、それらを読み取るのに 12 秒もかかります (「読み取り」テストを実行するときは、行をコメントアウトしますdo create_notes()
)。
起源
これは完全な例です (ビルドして実行します)。出力をコンソールに出力するだけです (ブラウザには出力しません)。
type User.t =
{ id : int
; notes : list(int) // a list of note ids
}
type Note.t =
{ id : int
; uid : int // id of the user this note belongs to
; content : string
}
db /user : intmap(User.t)
db /note : intmap(Note.t)
get_notes(uid:int) : list(Note.t) =
noteids = /user[uid]/notes
List.fold(
(h,acc ->
match ?/note[h] with
| {none} -> acc
| {some = note} -> [note|acc]
), noteids, [])
create_user() =
match ?/user[0] with
| {none} -> /user[0] <- {id=0 notes=[]}
| _ -> void
create_note() =
key = Db.fresh_key(@/note)
do /note[key] <- {id = key uid = 0 content = "note"}
noteids = /user[0]/notes
/user[0]/notes <- [key|noteids]
create_notes() =
repeat(1000, create_note)
page() =
do create_user()
do create_notes()
do Debug.alert("{get_notes(0)}")
<>Notes</>
server = one_page_server("Notes", page)
もう一つ
また、トランザクションを介してメモを取得しようとしました (以下を参照)。Db.transaction が適切なツールのように見えますが、それをうまく採用する方法が見つかりませんでした。get_notes_via_transaction
このメソッドは とまったく同じくらい遅いことがわかりましたget_notes
。
get_notes_via_transaction(uid:int) : list(Note.t) =
result = Db.transaction( ->
noteids = /user[uid]/notes
List.fold(
(h,acc ->
match ?/note[h] with
| {none} -> acc
| {some = note} -> [note|acc]
), noteids, [])
)
match result with
| {none} -> []
|~{some} -> some
ご協力いただきありがとうございます。
編集:詳細
役立つかもしれない少しの追加情報:
さらにテストを重ねた結果、最初の 100 レコードの書き込みに 5 秒しかかからないことがわかりました。各レコードは、前のレコードよりも書き込みに時間がかかります。500 番目のレコードでは、各レコードの書き込みに 5 秒かかります。
プログラムを中断して (プログラムが遅く感じ始めたときに) 再度開始すると (データベースをクリアせずに)、中断したときと同じ (遅い) ペースでレコードが書き込まれます。
これで解決に近づくでしょうか?