約 90k のドキュメントを含むデータベース (couchDB) があります。ドキュメントは次のように非常に単純です。
{
"_id": "1894496e-1c9e-4b40-9ba6-65ffeaca2ccf",
"_rev": "1-2d978d19-3651-4af9-a8d5-b70759655e6a",
"productName": "Cola"
}
いつかこのデータベースをモバイル デバイスと同期させたいと思っています。明らかに、90,000 件のドキュメントが一度に電話に送られるべきではありません。これが、フィルター関数を作成した理由です。これらは「productName」でフィルタリングすることになっています。最初は Javascript で、後で Erlang でパフォーマンスを向上させます。これらのフィルター関数は、JavaScript では次のようになります。
{
"_id": "_design/local_filters",
"_rev": "11-57abe842a82c9835d63597be2b05117d",
"filters": {
"by_fanta": "function(doc, req){ if(doc.productName == 'Fanta'){ return doc;}}",
"by_wasser": "function(doc, req){if(doc.productName == 'Wasser'){ return doc;}}",
"by_sprite": "function(doc, req){if(doc.productName == 'Sprite'){ return doc;}}"
}
}
Erlang では次のようになります。
{
"_id": "_design/erlang_filter",
"_rev": "74-f537ec4b6508cee1995baacfddffa6d4",
"language": "erlang",
"filters": {
"by_fanta": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Fanta\">> -> true; _ -> false end end.",
"by_wasser": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Wasser\">> -> true; _ -> false end end.",
"by_sprite": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Sprite\">> -> true; _ -> false end end."
}
}
簡単にするために、クエリはまだありませんが、「ハードコードされた」文字列です。フィルターはすべて機能します。問題は、彼らが遅くなることです。ドキュメントのフィルタリングにかかる時間をテストするために、最初に Java で、後に Perl でテストプログラムを作成しました。ここに私のPerlスクリプトの1つがあります:
$dt = DBIx::Class::TimeStamp->get_timestamp();
$content = get("http://127.0.0.1:5984/mobile_product_test/_changes?filter=local_filters/by_sprite");
$dy = DBIx::Class::TimeStamp->get_timestamp() - $dt;
$dm = $dy->minutes();
$dz = $dy->seconds();
@contArr = split("\n", $content);
$arraysz = @contArr;
$arraysz = $arraysz - 3;
$\="\n";
print($dm.':'.$dz.' with '.$arraysz.' Elements (JavaScript)');
そして今、悲しい部分です。これらは私が得る時間です:
2:35 with 2 Elements (Erlang)
2:40 with 10000 Elements (Erlang)
2:38 with 30000 Elements (Erlang)
2:31 with 2 Elements (JavaScript)
2:40 with 10000 Elements (JavaScript)
2:51 with 30000 Elements (JavaScript)
ところで、これらは分:秒です。数字はフィルターによって返された要素の数で、データベースには 90k 要素が含まれていました。大きな驚きは、Erlang フィルターがまったく高速ではないことでした。
すべての要素をリクエストするのにかかる時間はわずか 9 秒です。約 15 のビューを作成します。ただし、電話で使用してすべてのドキュメントを転送することはできません (ボリュームとセキュリティ上の理由から)。
ビューをフィルタリングしてパフォーマンスを向上させる方法はありますか? または、私の erlang フィルター関数に何か問題があります (JavaScript フィルターの時間に驚かないでください)。
編集: pgras で指摘されているように、これが遅い理由は、この質問への回答に掲載されています。erlang フィルターをより高速に実行するには、下の「レイヤー」に移動し、erlang を _design ドキュメントとしてではなく、データベースに直接プログラムする必要があります。しかし、どこから始めて、どのようにこれを行うべきか本当にわかりません。どんなヒントも役に立ちます。