Разбиение на страницы PHP с Couchbase становится очень медленным при большом количестве страниц

Я создал веб-приложение на основе PHP с нумерацией страниц. Я сделал версию для Couchbase и Postgres. Мне пришлось отказаться от N1QL, потому что у него была ужасная производительность (может быть, я задам еще один вопрос по этому поводу). Поэтому я перенес проект с N1QL на представления. Я заметил, что при небольшом количестве страниц (например, 1, 10, 50 с 48 записями на странице) производительность была лучше, чем у postgres (0,07 с против 0,11 с), но при большом количестве страниц (например, 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);
   }
}

person Mattia_98    schedule 26.07.2016    source источник
comment
Был бы рад изучить вашу разбивку на страницы N1QL, если вы разместите отдельный вопрос со своими запросами и индексами, а также версию EXPLAIN и Couchbase.   -  person geraldss    schedule 26.07.2016
comment
Спасибо, я сделал отдельный вопрос для этого, если вы хотите взглянуть. Я либо снова сделаю N1QL, если он сработает, дождусь Couchbase CE 4.5.0 и использую представления + полнотекстовый поиск, либо использую PostgreSQL.   -  person Mattia_98    schedule 27.07.2016


Ответы (1)


Это известное ограничение представлений. Проблема в том, что нет способа узнать, как далеко находится запись индекса представления 4000. Когда вы запрашиваете записи 4000-4004, механизм представления не должен генерировать только 5 записей, он должен генерировать 4000, которые он немедленно отбрасывает, а затем передает вам следующие 5. Из-за характера представлений и необходимости разбрасывать- собирать из нескольких узлов для получения одного результата, как вы заметили, это может быть чрезвычайно дорого. По этой причине не рекомендуется использовать опцию «пропустить».

Вместо этого рекомендуется использовать параметр «диапазон». Это работает так, чтобы изначально указать диапазон как открытый (т. е. такой, чтобы он включал все записи), например, от \u00 до ࿿ (полный диапазон символов Юникода) и вернуть, например. 10 записей. Затем вы помните, какой была 10-я запись, и указываете ее как начало диапазона для следующей страницы). Например, если вашей 10-й записью было «пиво», вы должны указать диапазон от «пиво» ​​до ࿿. Теперь это будет включать пиво в качестве первого результата, есть два способа решить эту проблему. Первый — запросить 11 результатов и игнорировать первый. Второй способ решить эту проблему — указать диапазон от 'beer\u00' до ࿿, который начинается с первой возможной записи после 'beer'.

Этот пост в блоге Couchbase содержит более подробную информацию: http://blog.couchbase.com/pagination-couchbase

Стоит отметить, что N1QL, как правило, имеет ту же проблему, что и не может угадать, где в индексе будет находиться n-я запись, и не обязательно будет ответом на вашу проблему.

person Chippiewill    schedule 14.08.2016