正規化されていないデータを集計する際にメモリ消費量を抑える方法

More than 1 year has passed since last update.

正規化されていない同じタイプのデータをCONCAT_WSで結合して取ってくる。

こうするとメモリ使用量を抑えることができます。

たぶんNULLカラムの個数が多いほど効果あると思います。

逆にNULLカラムが存在しない場合はたぶん効果ないと思います…。

コレクションで何やかんやしたい場合は使えませんがデータ集計のバッチとかでは使えるかなと。

とある案件で数百万件のデータを集計する際に20GBほど消費していたのがこの方法で半分の10GBになりました。

(リセマラ…コロス)

$data = [];

ModelClass::selectRaw("
id,
user_id,
CONCAT_WS(',', card_id01, card_id02, card_id03, card_id04) as card_ids,
CONCAT_WS(',', sub_card_id01, sub_card_id02, sub_card_id03, sub_card_id04) as sub_card_ids,
CONCAT_WS(',', weapon_id01, weapon_id02, weapon_id03, weapon_id04) as weapon_ids
"
)
->orderBy('id')
->chunk(10000, function ($chunk) use (&$data) {
foreach ($chunk as $v) {
$row = $v->toArray();
unset($row['id']);
$data[] = $row;
}
});

カラム名がidでない時はchunkByIdを使う。

chunkを使ってもエラーが出ないので注意。

$data = [];

ModelClass::selectRaw("
primary_id,
user_id,
CONCAT_WS(',', card_id01, card_id02, card_id03, card_id04) as card_ids,
CONCAT_WS(',', sub_card_id01, sub_card_id02, sub_card_id03, sub_card_id04) as sub_card_ids,
CONCAT_WS(',', weapon_id01, weapon_id02, weapon_id03, weapon_id04) as weapon_ids
"
)
->orderBy('primary_id')
->chunkById(10000, function ($chunk) use (&$data) {
foreach ($chunk as $v) {
$row = $v->toArray();
unset($row['primary_id']);
$data[] = $row;
}
}, 'primary_id');