我已经使用分页构建基于PHP的Web应用程序。我已经制作了Couchbase和Postgres版本。我不得不放弃N1QL,因为它有糟糕的表现(也许我会再提出另一个问题)。所以我将项目从N1QL迁移到了视图。我注意到,虽然页面编号较低(例如1,10,50,每页48条记录),但性能优于postgres(0.07s vs 0.11s),但页面编号较高(例如4000 - > 1.5秒和16000 - > 5秒)表现非常糟糕。我使用skip + limit对原生CB库进行分页。
有什么想法吗?
PHP:
public static function findByPage($recordsPerPage, $page) {
$query = CouchbaseViewQuery::from("dev_".static::COLLECTION_NAME, "get_".static::COLLECTION_NAME."")->reduce(false)->skip($recordsPerPage*($page-1))->limit($recordsPerPage)->custom(array("full_set"=> "true"));
$data = DB::getDB()->query($query, null, true);
// var_dump($data);
$objects = array();
foreach($data["rows"] as $row) {
$objects[] = static::find($row["key"]);
}
return $objects;
}
其中一个观点(它们几乎完全相同):
function (doc, meta) {
if(doc.collection == "green_area") {
emit(doc._id, null);
}
}
答案 0 :(得分:0)
这是视图的已知限制。问题是没有办法知道视图索引记录4000有多远。当您请求记录4000-4004时,视图引擎不必生成仅5条记录,它必须生成4000它立即丢弃然后将您交给下一条5.由于视图的性质而不得不从多个节点分散 - 聚集以产生单个结果,这可能是非常昂贵的,如您所观察到的。出于这个原因,不鼓励使用' skip'选项
相反,建议您使用'范围'选项。这种方式的工作方式是最初将范围指定为开放(即,它将包括所有记录),其示例将是从\ u00到\ u0fff(完整范围的unicode字符)并返回例如10条记录。然后,您将记住第10条记录是什么,并将其指定为下一页的范围的开头)。例如,如果你的第10个记录是啤酒'然后你要指定啤酒'的范围。到\ u0fff。现在这将包括啤酒作为第一个结果,有两种方法来解决这个问题。第一个是请求11个结果而忽略第一个结果。解决这个问题的第二种方法是将范围指定为' beer \ u00'在“啤酒”之后的第一个可能的记录开始的\ u0ff。
此Couchbase博客文章详细介绍了http://blog.couchbase.com/pagination-couchbase
值得注意的是,N1QL通常会遇到无法猜测第n条记录在索引中的位置的问题,并且不一定能解决您的问题。