Pages

2023年9月6日水曜日

CakePHP4 DBの複数レコード情報を一気に取得するとメモリーが足りないのでに少しずつ取得する

今回はCSV出力する際にレコード数が多くてメモリー不足にならない方法を考えていました。

CakePHP 4では、`enableBufferedResults`を利用してメモリー不足を発生させないようにすることができます。この設定は、データベースから大量のデータを取得する場合など、メモリーを効率的に管理するために役立ちます。

まずは公式ドキュメントの紹介
https://book.cakephp.org/4/ja/orm/retrieving-data-and-resultsets.html#id16

`enableBufferedResults`を有効にすると、CakePHPはデータベースのクエリ結果をメモリーに全て読み込むのではなく、イテレータを使用してデータを一部ずつ取得できるようになります。これにより、大規模なデータセットを取り扱う場合でもメモリー不足の問題を回避できます。

以下は、CakePHP 4で`enableBufferedResults`を設定する方法です。

1. コントローラーまたはモデルのアクション内で、`enableBufferedResults`を有効にします。たとえば、以下のように設定できます。

// コントローラーのアクション内で
public function getData() {
    // データベースから大量のデータを取得するクエリ
    $query = $this->Table->find()->enableBufferedResults();

    // データを取得
    foreach ($query as $row) {
        // データの処理
    }
}

2. 上記の例では、`enableBufferedResults`をクエリオブジェクトに適用し、`foreach`ループを使用してデータを一つずつ処理しています。この方法を使用することで、メモリー不足を回避できます。

注意事項:

- `enableBufferedResults`を有効にしてループしてる時などは別のクエリーを投げる事はできません。(多分。。)DBコネクションを追加して対応する方法もありますが、接続数をその分消費してしまうため可能であれば避けたい方法ではあります。

- `enableBufferedResults`を有効にすると、イテレータが内部で使用され、データベースの接続がクローズされると自動的にクリーンアップされます。

- 大規模なデータセットを処理する場合、`enableBufferedResults`を有効にしても、パフォーマンスの問題が発生する可能性があるため、適切なインデックスやクエリの最適化も検討してください。

- メモリーの使用状況に注意し、必要な場合には適切なタイミングで不要なリソースを解放することをお勧めします。

Followers