私は非常に遅い PDOStatement::fetchAll() に遭遇しました。私のクエリは 0.1 秒未満で実行されます。また、MySQL ターミナルでは、0.1 秒未満で画面に出力が表示されます。しかし、PDOStatement で fetchAll() を実行するには 2.5 秒かかります。
// $_DB is my PDO class instance.
$tStart = microtime(true);
$q = $_DB->prepare('SELECT id FROM ... WHERE ... LIMIT 1000');
$q->execute($aArgs);
var_dump(round(microtime(true) - $tStart, 5));
$aIDsFiltered = $q->fetchAll(PDO::FETCH_COLUMN, 0);
var_dump(round(microtime(true) - $tStart, 5));exit;
これは以下を出力します:
float(0.0612)
float(2.58708)
よし、真剣に?MySQL コンソールで結果を 0.1 秒未満で取得するにはどうすればよいですか?PHP では、これらの 1000 件の結果をフェッチして単純な配列に入れるのに 2.5 秒かかりますか? さあ、1000個の数字を1つずつ配列に入れる単純なforループは0.001秒かかります...!!! ここで何が欠けていますか?代わりに何を使用できますか? 私はグーグルで検索しましたが、解決策が見つかりません:(事前に感謝します!
編集: fetchAll() の期間は、返される結果の数に関連するだけでなく、$aArgs のサイズにも関連します。引数を送信しないと、結果が 50K であっても fetchAll() は 0.01 秒で返されます。execute() 呼び出しに 47K の引数を与えると、fetchAll() の実行に 120 秒かかります。しかし、これを引き起こすのは大きなクエリ文字列の作成ではありません (ちなみに execute() はそうしませんか?)、同じ 47K の引数ですが、1K の結果への LIMIT には 2.5 秒しかかからないためです...示唆されているように、 EXPLAIN 出力が PDO と MySQL コンソールの使用で同じであることを確認しました。また、MySQL が懸命に動作しているとは思えません。CPU を常に消費しているのは Apache プロセス (したがって PHP) です。また、古い mysql_* インターフェイスを使用すると、結果の取得に 0.03 秒かかります。
背景情報
好奇心旺盛な人のために:
- これはローカルの MySQL 5.5 データベースであるため、リモート サーバーではありません。
- PHP バージョン: 5.4.4。
- ここでの使用例は、システム内に多数のフィルターがあり (1 つのフィルター = 1 つのデータベース クエリ)、ユーザーの好みの順序で実行され、各フィルターが前のフィルター実行から一致するエントリの ID を取得し、残りの一致するエントリの ID を返す必要があります (これが明確であることを願っています)。このように、フィルタは最終的に、すべてのフィルタに一致するデータベース エントリの小さなサブセットを選択するために使用されます。
- 実際には 47,000 件の結果が返されることがありますが、遅延は 2.1 分ですが、クエリの所要時間は 1 秒未満であり、私の場合は許容できません。
- 複数のフィルターを 1 つのデータベース クエリに組み合わせることで、結果の数を大幅に減らすことができることを理解しています。ただし、フィルターはユーザーによって選択され (したがって、組み合わせは無制限)、さまざまなデータベース テーブルで結合とチェックを行うことができ、最後に重要なこととして、各フィルターが返す結果の数に関する統計を表示したいと考えています。