Пагинатор Zend Framework (Zend_Paginator) работает слишком медленно - PullRequest
2 голосов
/ 10 февраля 2010

У меня слишком медленный запрос.загрузка страницы занимает несколько минут.Я делаю соединение таблиц с таблицами с более чем 100 000 записей.В моем запросе он захватывает все записи или получает только ту сумму, которая мне нужна для страницы?Нужно ли устанавливать ограничение в запросе?Если я это сделаю, разве это не даст пагинатору неверный счет?

$paymentsTable = new Donations_Model_Payments();
$select = $paymentsTable->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
$select->setIntegrityCheck(false)
    ->from(array('p' => 'tbl_payments'), array('clientid', 'contactid', 'amount'))
    ->where('p.clientid = ?', $_SESSION['clientinfo']['id'])
    ->where('p.dt_added BETWEEN  \''.$this->datesArr['dateStartUnix'].'\' AND \''.$this->datesArr['dateEndUnix'].'\'')
        ->join(array('c' => 'contacts'), 'c.id = p.contactid', array('fname', 'mname', 'lname'))
        ->group('p.id')
        ->order($sortby.' '.$dir)
        ;
        $payments=$paymentsTable->fetchAll($select);

// paginator
$paginator = Zend_Paginator::factory($payments);
$paginator->setCurrentPageNumber($this->_getParam('page'), 1);
$paginator->setItemCountPerPage('100'); // items pre page
$this->view->paginator = $paginator;

$payments=$payments->toArray();
$this->view->payments=$payments;

Ответы [ 3 ]

3 голосов
/ 10 февраля 2010

Пожалуйста, смотрите исправленный код ниже. Вам необходимо передать $select в Zend_Paginator через правильный адаптер. В противном случае вы не увидите преимуществ в производительности.

$paymentsTable = new Donations_Model_Payments();
$select = $paymentsTable->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
$select->setIntegrityCheck(false)
    ->joinLeft('contacts', 'tbl_payments.contactid = contacts.id')
    ->where('tbl_payments.clientid = 39')
    ->where(new Zend_Db_Expr('tbl_payments.dt_added BETWEEN "1262500129" AND "1265579129"'))
    ->group('tbl_payments.id')
    ->order('tbl_payments.dt_added DESC');

// paginator
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_DbTableSelect($select));
$paginator->setCurrentPageNumber($this->_getParam('page', 1));
$paginator->setItemCountPerPage('100'); // items pre page
$this->view->paginator = $paginator;

См. Пересмотренный код выше!

2 голосов
/ 10 февраля 2010

В вашем коде вы:

  • сначала, выбирая и выбирая все записи, которые соответствуют вашему состоянию
    • см. select ... from ... и все такое
    • и вызов fetchAll на линии сразу после
  • и, только, вы используете пагинатор,
    • о результатах, возвращаемых вызовом fetchAll.

При этом я бы сказал, что да, все ваши 100 000 записей извлекаются из БД, которыми управляет PHP, передаются в Zend_Paginator, который должен работать с ними ... только для того, чтобы отбросить почти все из них.


Используя Zend_Paginator, вы сможете передать ему экземпляр Zend_Db_Select и позволить ему выполнить запрос, указав требуемый limit.

Возможно, пример с DbSelect и адаптером DbTableSelect может помочь вам понять, как этого можно достичь (извините, у меня нет рабочего примера) .

1 голос
/ 17 февраля 2010

Я лично считаю результаты через COUNT (*) и передаю их в zend_paginator. Я так и не понял, почему вы глубоко связали zend_paginator с результатами базы данных. Я вижу плюсы и минусы, но на самом деле это далеко не так.

Учитывая, что вам нужно только 100 результатов, вы получаете 100'000+, а затем zend_paginator их выбрасывает. Реально вы хотите просто дать ему счет.

    $items      = Eurocreme_Model::load_by_type(array('type' => 'list', 'from' => $from, 'to' => MODEL_PER_PAGE, 'order' => 'd.id ASC'));
    $count      = Eurocreme_Model::load_by_type(array('type' => 'list', 'from' => 0, 'to' => COUNT_HIGH, 'count' => 1));

    $paginator = Zend_Paginator::factory($count);
    $paginator->setItemCountPerPage(MODEL_PER_PAGE);
    $paginator->setCurrentPageNumber($page);

    $this->view->paginator = $paginator;
    $this->view->items = $items;
...