【问题标题】:cakephp paginate using mysql SQL_CALC_FOUND_ROWScakephp 使用 mysql SQL_CALC_FOUND_ROWS 分页
【发布时间】:2011-02-17 02:31:26
【问题描述】:

我正在尝试让 Cakephp 分页利用 mysql 中的 SQL_CALC_FOUND_ROWS 功能在使用 LIMIT 时返回总行数。希望这样可以消除 paginateCount(),然后是 paginate() 的双重查询。

我已经把它放在了我的 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}`.*";

问:如何获得 paginate() 中使用的 SAME 限制值?

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

问:我们能否以某种方式让查询结果直接分页,而不需要额外的查询?

    $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);

问:我们能否以某种方式直接从 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
}

【问题讨论】:

  • 我只想在这里补充一点,SQL_CALC_FOUND_ROWS 通常比使用直接 COUNT() 和 2 个查询慢得多。原因是Mysql如何寻找数据。尤其是在大型数据集上,SQL_CALC_FOUND_ROWS 解决方案可能需要数百万倍的时间(100 多秒与 0.004 秒跨越一百万条记录)。

标签: php mysql cakephp pagination


【解决方案1】:

我为从返回当前页面的结果和同一响应中可用结果总数的 Web 服务分页结果解决此问题的方法是将分页属性从控制器复制到控制器操作中的模型, 在你调用 $this->paginate(); 之前这样我的分页设置就可以在模型的 paginateCount() 方法中使用。然后在 paginateCount() 中发出对 web 服务的调用以获取结果。然后将结果存储在模型的属性中,然后返回可用结果的总数。然后在模型的 paginate() 方法中,返回我获取并存储在 paginateCount() 方法中的结果。

也许这些方面的东西也适合你?

【讨论】:

  • 我使用了一个类静态变量来缓存 paginateResponse,但我从未想过我也可以通过相同的机制传递分页选项。只要我可以设置recursive=-1,它似乎就可以正常工作,但是如果分页中有关联,那么在关联查询之后会调用“SELECT FOUND ROWS”,并返回错误的结果。
  • 也很难在 find() 中正确获取 $fields 值。当前使用 $fields = is_array($fields) ? array_unshift($fields, 'SQL_CALC_FOUND_ROWS') : !empty($fields) ? array('SQL_CALC_FOUND_ROWS', $fields) : "SQL_CALC_FOUND_ROWS {$this->alias}.*";但实际上只测试了 $fields=;;
猜你喜欢
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-30
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
相关资源
最近更新 更多