2010-02-10 91 views
2

我有一個查詢,運行的方式太慢。該頁面需要幾分鐘才能加載。 我正在做超過100,000條記錄的表的表連接。在我的查詢中,是抓取所有記錄還是僅獲取我需要的頁面數量?我需要在查詢中添加一個限制嗎?如果我這樣做,這不會給分頁器錯誤的記錄數嗎?zend框架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結果運行。下面是查詢: SELECT tbl_payments.clientid,tbl_payments.contactid,tbl_payments.amount, 觸點.fname,contacts.mname,contacts.lname FROM tbl_payments LEFT JOIN'contacts' ON contacts.id = tbl_payments.contactid WHERE tbl_payments.clientid = 39 AND(tbl_payments.dt_added BETWEEN '1262500129' AND '1265579129') GROUP BY tbl_payments.id ORDER BY tbl_payments.dt_added DESC – EricP 2010-02-11 04:21:40

+0

見上文訂正代碼.. – Simon 2010-02-11 13:57:21

+0

有一種使用一個普通的方式sql查詢用於paginator?也許它會適用於此。 – EricP 2010-02-12 01:14:29

2

在代碼中,你是:

  • 第一,選擇和獲取匹配您的條件
    • 看到select ... from所有記錄......和所有
    • 和撥打電話fetchAll就在
    • 之後
  • 和,只有你正在使用的分頁程序,
    • fetchAll調用返回的結果。

就這樣,我會說,是的,你的所有10萬條記錄是從數據庫,通過PHP操縱,傳遞給Zend_Paginator具有獲取與他們合作,只...幾乎放棄他們全部。


使用Zend_Paginator,你應該能夠通過它的一個實例的Zend_Db_Select,讓它執行查詢,指定所需的limit

也許關於DbSelect and DbTableSelect adapter的例子可能會幫助您瞭解如何實現這一點(對不起,我沒有任何工作示例)

+0

但是,如果我對查詢使用限制,分頁結果是不是不正確?它可能會顯示錯誤的頁面數量,因爲我告訴它結果較少。或者我需要做2個查詢,一個用於分頁器,另一個用於查詢結果?不確定。 – EricP 2010-02-10 12:56:13

+0

你不應該*(根據我的理解)*自己做一個查詢:你應該讓'Zend_Paginator'執行查詢,指定正確的'limit'本身 - 它會知道正確數量的頁面一個'count'查詢,我想) – 2010-02-10 12:59:19

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;