2010-02-10 2 views
2

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

$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

См. Пересмотренный код ниже. Вы должны передать $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; 

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

+0

Спасибо, Саймон, но я попробовал, и он все еще просто висит там. Если я запускаю тот же запрос через PhpMyAdmin, он запускается через секунду с 16 000 результатов. Вот запрос: ВЫБРАТЬ tbl_payments.clientid, tbl_payments.contactid, tbl_payments.amount, контакты .fname, contacts.mname, contacts.lname ОТ tbl_payments LEFT JOIN 'contacts' ON ​​contacts.id = tbl_payments.contactid WHERE tbl_payments.clientid = 39 И (tbl_payments.dt_added МЕЖДУ '1262500129' И '1265579129') GROUP BY tbl_payments.id ORDER BY DESC tbl_payments.dt_added – EricP

+0

См пересмотренный код выше .. – Simon

+0

есть ли способ использовать просто sql-запрос для использования в paginator? Может быть, это сработает с этим. – EricP

2

В коде, вы:

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

С этим, я бы сказал, что да, все ваши 100000 записи извлекаются из базы данных, манипулируют PHP, передается Zend_Paginator, который должен работать с ними ... только отказаться от почти все они.


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

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

+0

Но если я использую ограничение по запросу, не будут ли неверны результаты разбивки на страницы? Это может показаться неправильным количеством страниц, потому что я говорю, что результатов меньше. Или мне нужно сделать 2 запроса, один для paginator и один для результатов? Не уверен. – EricP

+0

Вы не должны * (из того, что я понимаю) * сделать запрос самостоятельно: вы должны позволить 'Zend_Paginator' делать запрос, указав правильный' limit' сам, и он будет знать правильное количество страниц (это будет делать запрос 'count', я полагаю) –

1

Я лично рассчитываю результаты через 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;