私はZF2パージネーターをいくつかの大規模な(最悪の場合にはサーチフィルターなしで1000万回)レコードセットで使用しようとしています。私のテーブルはInnoDBフォーマットであり、私はメタデータの一部として明確なカウントを保持していないと理解しています。InnoDBテーブルのZF2ページネイターを使ったCount()の異常なパフォーマンス
私はZend \ Paginator \ Adapter \ DbSelectクラスを拡張し、別のテーブルに手動で格納するカウントデータを使用する独自のcount()メソッドを実装できることを認識していますが、カウントを格納する方法は不明です検索の可能性のあるすべての順列。
デフォルトZF2 DbSelect adapterは、このメソッドを使用しています。ここでは
<?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秒で完了し(確かにうまくいきません)、730万レコードが返されます。ここで
は、内側のクエリからEXPLAIN(カウント1にEXPLAINまた、RDSサーバー上のためのディスク・スペースのダイ)されています
+----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ | 1 | SIMPLE | contacts | ref | trash | trash | 1 | const | 3441317 | | +----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ 1 rows in set (0.04 sec)
は、この優れたチューニングを行うことができることはありますか? ZF2 Paginatorが、InnoDBが何らかの方法で、何らかの形で互換性のないカウントを処理する方法ですか?データベース内のほとんどのフィールドの検索を許可している場合、他の人が可能なすべてのクエリのキャッシュカウントをどのように処理しますか?
事前のおかげで...
この問題は、InnoDBに固有の問題です。この問題は、メタデータ内のテーブル内の行数を追跡するため、この問題はありません。クエリをデータベースのUIで微調整し、それがどのような影響を及ぼすかを確認するのが最善の方法です。 COUNT(1)の代わりに、COUNT(ID)を試すか、mysql> select count(1)from ... index(your_index)を使用して特定のインデックスを使用するようにMySQLに指示してください。 – Ruben
** COUNT 15分36秒; ** COUNT(ID)**:18分8.83秒 – jcq