我正在尝试在一些大型(在最坏的情况下大约 1000 万不带搜索过滤器的情况下)记录集上使用 ZF2 Paginator。我的表采用 InnoDB 格式,据我所知,它没有作为元数据的一部分保留明确的计数。
我意识到我可以扩展 Zend\Paginator\Adapter\DbSelect 类并实现我自己的 count() 方法,该方法使用我手动存储在另一个表中的计数数据,但我不确定如何存储所有可能排列的计数可能进行的搜索。
默认的ZF2 DbSelect 适配器使用此方法:
<?php
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
$select = clone $this->select;
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
$select->reset(Select::ORDER);
$countSelect = new Select;
$countSelect->columns(array('c' => new Expression('COUNT(1)')));
$countSelect->from(array('original_select' => $select));
$statement = $this->sql->prepareStatementForSqlObject($countSelect);
$result = $statement->execute();
$row = $result->current();
$this->rowCount = $row['c'];
return $this->rowCount;
}
?>
这是该方法为我生成的一个非常简单的示例查询:
SELECT
COUNT(1) AS `c`
FROM
(
SELECT
`contacts`.`id` AS `id`,
`contacts`.`firstname` AS `firstname`,
`contacts`.`middlename` AS `middlename`,
`contacts`.`lastname` AS `lastname`,
`contacts`.`gender` AS `gender`
FROM
`contacts`
WHERE
`contacts`.`trash` = '0'
) AS `original_select`
我不确定 MyISAM 表上的性能如何,但这对我来说失败了,因为它占用了运行它的 Amazon RDS(25GB,db.m1.small)实例上的所有可用空间。作为比较,仅运行内部(原始)查询,它在 100 秒内完成(当然不好)并返回 739 万条记录。
这是来自内部查询的解释(由于 RDS 服务器上的磁盘空间,计数上的解释也死了):
+----+-------------+----------+------+------------ ---+-------+---------+--------+---------+-------+ | 编号 | 选择类型 | 表| 类型 | 可能的键 | 关键 | key_len | 参考 | 行 | 额外 | +----+-------------+----------+------+------------ ---+-------+---------+--------+---------+-------+ | 1 | 简单 | 联系方式 | 参考 | 垃圾 | 垃圾 | 1 | 常量 | 3441317 | | +----+-------------+----------+------+------------ ---+-------+---------+--------+---------+-------+ 1 行(0.04 秒)
有什么办法可以更好地调整这个吗?ZF2 Paginator 处理计数的方式在某种程度上与 InnoDB 的处理方式不兼容吗?如果我们允许对数据库中的大多数字段进行搜索,其他人将如何处理所有可能查询的缓存计数?
提前致谢...