Laravel の ORM Eloquent chunk() メソッドに問題があります。結果が一部欠落しています。テスト クエリは次のとおりです。
$destinataires = Destinataire::where('statut', '<', 3)
->where('tokenized_at', '<', $date_active)
->chunk($this->chunk, function ($destinataires) {
foreach($destinataires as $destinataire) {
$this->i++;
}
}
echo $this->i;
124838 件の結果が返されます。
しかし :
$num_dest = Destinataire::where('statut', '<', 3)
->where('tokenized_at', '<', $date_active)
->count();
echo $num_dest;
結果は 249676 なので、最初のコード例の 2 倍になります。
私のスクリプトは、データベース内の一致するすべてのレコードを編集することになっています。これを複数回起動すると、そのたびに残りのレコードの半分だけが渡されます。
モデルの代わりに DB::table() を試しました。->take(20000) を追加しようとしましたが、考慮されていないようです。->toSql() でクエリをエコーしましたが、すべて問題ないようです (->take() パラメータを追加すると、LIMIT 句が追加されます)。
助言がありますか ?
ベストアンサー1
チャンク メソッドを使用してすべてのレコードを削除するとします。テーブルには 2,000,000 件のレコードがあり、それらをすべて 1000 チャンクで削除します。
$query->orderBy('id')->chunk(1000, function ($items) {
foreach($items as $item) {
$item->delete();
}
});
次のようなクエリで最初の 1000 件のレコードを取得して、最初の 1000 件のレコードを削除します。
SELECT * FROM table ORDER BY id LIMIT 0,1000
チャンク メソッドからの他のクエリは次のようになります。
SELECT * FROM table ORDER BY id LIMIT 1000,2000
ここで問題となるのは、1000 件のレコードを削除して、1000 件から 2000 件までの結果を取得することです。実際には最初の 1000 件のレコードが欠落しており、これはチャンクの最初のステップで 1000 件のレコードを削除しないことを意味します。このシナリオは他のステップでも同じです。各ステップで 1000 件のレコードが欠落しており、これがこれらの状況で最適な結果が得られない理由です。
削除の例を作成しました。この方法により、チャンク メソッドの正確な動作を知ることができるためです。
アップデート:
安全に削除するために使用できますchunkById()
。
詳細はこちらをご覧ください:
http://laravel.at.jeffsbox.eu/laravel-5-eloquent-builder-chunk-chunkbyid https://laravel.com/api/5.4/Illuminate/Database/Eloquent/Builder.html#method_chunkById