ardggy's blog

Esc - Meta - Alt - Ctrl - Shift

ジェネレータとSQL

SQL の結果をなめたいがメモリにぜんぶ展開すると out of memory になりがちなところ、 チャンクを次々とジェネレータで供給するというパターンを思いついた。これならほぼ定数メモリで大量のデータを処理できる。

ジェネレータは Iterator を実装しているので、SPL のイテレータにわたすこともできる。

function chunk(SQL $query, int $size) : Iterator {
  $offset = 0;
  $query->limit($size);
  while ($result = fetch_all($query)) {
    yield from $result;

    $query->offset($offset += $size);
  }
}

$query = sql("SELECT * FROM sakila.film"); // SQL を表すナニカ
foreach (chunk($query, $size = 1000) as $film) {
  # do useful stuff
}

実際は offset ではなく、id ベースでたどるのがよさそうではある。