简体   繁体   English

Couchbase的PHP分页在高页面数时变得非常慢

[英]PHP pagination with Couchbase gets very slow at high page numbers

I've build a PHP based webapp with pagination. 我已经建立了一个带有分页功能的基于PHP的webapp。 I've made both a Couchbase and a Postgres version. 我已经制作了Couchbase和Postgres版本。 I had to abandon N1QL because it had terrible performance (maybe I'll make another question for that). 我不得不放弃N1QL,因为它的性能很差(也许我会对此提出另一个问题)。 So I migrated the project from N1QL to views. 因此,我将项目从N1QL迁移到了视图。 I noticed that, while at low page number (eg 1, 10, 50 with 48 records per page) performance was better than postgres (0.07s vs 0.11s), but at a high page number (eg 4000 -> 1.5 seconds and 16000 -> 5 seconds) performance is very bad. 我注意到,虽然在低页数(例如1、10、50,每页48条记录)下,性能优于postgres(0.07s对0.11s),但是在高页数(例如4000-> 1.5秒和16000)下-> 5秒),效果非常糟糕。 I use skip + limit for pagination with native CB library. 我使用跳过+限制与本机CB库分页。

Any ideas? 有任何想法吗?

PHP: 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;
    }

One of the views (they are pretty much all the same): 一种视图(它们几乎完全相同):

function (doc, meta) {
  if(doc.collection == "green_area") {
    emit(doc._id, null);
   }
}

This is a known limitation with views. 这是视图的已知限制。 The issue is that there is no way to know how far through the view index record 4000 is. 问题在于,无法知道视图索引记录4000的距离。 When you request records 4000-4004, the view-engine doesn't have to generate just 5 records, it has to generate 4000 that it immediately discards and then hands you the next 5. Due to the nature of views and having to scatter-gather from multiple nodes to produce a single result this can be extremely expensive as you have observed. 当您请求记录4000-4004时,视图引擎不必仅生成5条记录,它必须生成4000条记录,该记录会立即丢弃,然后再交给您下一条5条记录。由于视图的本质以及分散性,从多个节点收集以产生单个结果,正如您所观察到的,这可能是非常昂贵的。 For this reason it is discouraged to use the 'skip' option 因此,不建议使用“跳过”选项

Instead it is recommended that you use the 'range' option. 相反,建议您使用“范围”选项。 The way this works is to initially specify the range as open (ie. such that it would include all records), an example of this would be from \\u00 to \࿿ (The full range of unicode characters) and to return eg 10 records. 此方法的工作方式是首先将范围指定为open(即,使其包括所有记录),例如,从\\ u00到\\ u0fff(完整的Unicode字符范围)并返回例如10条记录。 You would then remember what the 10th record was and specify that as the start of your range for the next page). 然后,您将记住第10条记录,并将其指定为下一页范围的开始)。 For instance if your 10th record was 'beer' then you would specify the range from 'beer' to \࿿. 例如,如果您的第十条记录是“啤酒”,那么您将指定从“啤酒”到\\ u0fff的范围。 Now this would include beer as the 1st result, there are two ways to resolve this. 现在这将包括啤酒作为第一结果,有两种解决方法。 The first is to request 11 results and ignore the first. 第一个是请求11个结果,而忽略第一个。 The second way to resolve this would be to specify the range as 'beer\\u00\u0026#39; to \࿿ which starts at the first possible record after 'beer'. 解决此问题的第二种方法是将范围指定为'beer \\ u00'到\\ u0fff,该范围始于'beer'之后的第一个可能的记录。

This Couchbase blog post goes into more details: http://blog.couchbase.com/pagination-couchbase 该Couchbase博客文章中有更多详细信息: http : //blog.couchbase.com/pagination-couchbase

It's worth noting that N1QL will generally have the same problem of not being able to guess where the nth record will be in the index and will not necessarily be the answer to your problem. 值得注意的是,N1QL通常会遇到相同的问题,即无法猜测索引中的第n条记录,并且不一定能解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM