2010-05-08 3 views
3

Cakephp 페이지 매기기가 LIMIT을 사용하는 동안 총 행 수를 반환하기 위해 mysql의 SQL_CALC_FOUND_ROWS 기능을 활용하도록하려고합니다. 다행히 paginateCount(), paginate()의 이중 쿼리를 제거 할 수 있기를 바랍니다.mysql을 사용하여 cakephp 페이지 매기기 SQL_CALC_FOUND_ROWS

내 app_model.php에 넣고 한, 그것은 기본적으로 작동하지만, 더 잘 할 수있다. 누군가가 paginate/paginateCount를 재정의하는 방법을 알아내어 1 SQL stmt 만 실행하도록 도와 줄 수 있습니까?

/** 
* Overridden paginateCount method, to using SQL_CALC_FOUND_ROWS 
*/ 
public function paginateCount($conditions = null, $recursive = 0, $extra = array()) { 
    $options = array_merge(compact('conditions', 'recursive'), $extra); 
    $options['fields'] = "SQL_CALC_FOUND_ROWS `{$this->alias}`.*"; 

Q : paginate()에 사용 된 SAME 한도는 어떻게 받습니까?

$options['limit'] = 1; // ideally, should return same rows as in paginate()  

Q : 추가 쿼리 없이도 쿼리 결과가 어떻게해서 페이지 매김되도록 할 수 있습니까?

$cache_results_from_paginateCount = $this->find('all', $options); 
    /* 
    * note: we must run the query to get the count, but it will be cached for multiple paginates, so add comment to query 
    */ 
    $found_rows = $this->query("/* do not cache for {$this->alias} */ SELECT FOUND_ROWS();"); 
    $count = array_shift($found_rows[0][0]); 
    return $count; 
} 

/** 
* Overridden paginate method 
*/ 
public function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) { 
    $options = array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'), $extra); 

Q : 우리가 어떻게 든) (paginateCount에서 직접 $ cache_results_for_paginate을받을 수 있나요?

return $cache_results_from_paginateCount; // paginate in only 1 SQL stmt 
    return $this->find('all', $options); // ideally, we could skip this call entirely 
} 
+0

여기서는 SQL_CALC_FOUND_ROWS가 직선 COUNT() 및 2 개의 쿼리를 사용하는 것보다 훨씬 느리고 종종 추가하기를 원합니다. 그 이유는 MySQL이 데이터를 찾는 방법입니다. 대용량 데이터 세트 특히 SQL_CALC_FOUND_ROWS 솔루션은 말 그대로 수백만 번 더 오래 걸릴 수 있습니다 (백만 초 동안 100 초 이상 0.004 초). – Oddman

답변

0

나는 현재 페이지와 동일한 응답에서 사용할 수있는 결과의 총 수에 대한 결과를 반환하는 웹 서비스에서 결과를 paginating 위해이 문제를 해결하는 방법은 모델에 컨트롤러에서 PAGINATE 속성을 복사하는 것입니다 컨트롤러 액션에서 $ this-> paginate();를 호출하기 전에; 내 페이징 설정은 모델의 paginateCount() 메소드에서 사용할 수 있습니다. 그런 다음 paginateCount()에서 결과를 얻기 위해 webservice에 대한 호출을 실행합니다. 그런 다음 결과를 모델의 속성에 저장 한 다음 사용 가능한 결과의 총 개수를 반환합니다. 그런 다음 모델의 paginate() 메서드에서 가져 와서 paginateCount() 메서드에 저장 한 결과를 반환합니다.

아마도 이러한 행을 따라 무언가가 도움이 될 것입니까?

+0

paginateResponse를 캐시하기 위해 static var 클래스를 사용했지만 동일한 메커니즘을 통해 페이지 매김 옵션을 전달할 수는 없었습니다. 재귀 = -1을 설정할 수있는 한 제대로 작동하는 것처럼 보이지만 페이지 매김에 연결이 있으면 연결 쿼리 후에 "SELECT FOUND ROWS"가 호출되어 잘못된 결과를 반환합니다. – michael

+0

또한 find()에서 $ fields 값을 올바르게 얻는 데 어려움을 겪습니다. 현재 사용 중 $ fields = is_array ($ fields) ? array_unshift ($ fields, 'SQL_CALC_FOUND_ROWS') :! empty ($ fields)? 배열 ('SQL_CALC_FOUND_ROWS', $ fields) : "SQL_CALC_FOUND_ROWS'{$ this-> alias}'. *"; 하지만 실제로는 $ fields = ;; – michael