我有一个数据库(couchDB),里面有大约 90k 个文档。文件非常简单,如下所示:
{
"_id": "1894496e-1c9e-4b40-9ba6-65ffeaca2ccf",
"_rev": "1-2d978d19-3651-4af9-a8d5-b70759655e6a",
"productName": "Cola"
}
现在我想有一天将这个数据库与移动设备同步。显然 90k 文档不应该一次全部转到电话上。这就是我编写过滤器函数的原因。这些应该按“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 脚本之一:
$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 文档。但我真的不知道从哪里开始以及如何做到这一点。任何提示都会有所帮助。