Optimumkan gelung foreach Laravel dengan 2k dan tingkatkan pengambilan semula hubungan daripada 200k untuk mengurangkan masa pelaksanaan
P粉707235568
P粉707235568 2024-03-30 13:42:11
0
2
483

Saya mempunyai model yang dipanggil "Produk" Saya mempunyai model bernama Note_voucher_line

Ini adalah hubungan dalam produk

public function get_note_voucher_lines()
{
    return $this->hasMany('App\Models\Note_voucher_line','product_id','id')->orderBy('date','asc')->orderBy('note_voucher_id','asc');
}

Sekarang kadang-kadang saya perlu menggelungkan produk dengan kod seperti ini

$products = Product::whereBetween('id',[$num1,$num2])->get();
foreach($products as $product)
{
    $lines = $product['get_note_voucher_lines'];
    // when i use this relation it tack long long time
}

Model Note_voucher_line mempunyai lebih 300k baris Saya mempunyai indeks pada migration Ini ialah note_voucher_linespenghijrahan indeks dalaman

Schema::table('note_voucher_lines', function($table) {
    $table->foreign('note_voucher_id')->references('id')->on('note_vouchers');
    $table->foreign('user_id')->references('id')->on('users');
    $table->foreign('journal_entry_id')->references('id')->on('journal_entries');
    $table->foreign('warehouse_id')->references('id')->on('warehouses');
    $table->foreign('product_id')->references('id')->on('products');
    $table->foreign('cost_center_id')->references('id')->on('cost_centers');
    $table->foreign('unit_id')->references('id')->on('units');
    $table->foreign('is_it_bonus')->references('id')->on('status');
    $table->foreign('note_voucher_type_id')->references('id')->on('note_voucher_types');
    $table->foreign('posting_state_id')->references('id')->on('posting_status');
    $table->foreign('product_total_quantity_id')->references('id')->on('product_total_quantitys');
    $table->foreign('is_componentable')->references('id')->on('status');
    $table->foreign('approved_state_id')->references('id')->on('approval_status');
    $table->foreign('currency_id')->references('id')->on('currencies');
    $table->foreign('branch_id')->references('id')->on('branches');
    $table->foreign('created_by')->references('id')->on('users');
    $table->foreign('deleted_by')->references('id')->on('users');
});

Jadual produk mempunyai indeks yang dipanggil product_id Sebarang bantuan di sini untuk menjadikannya lebih pantas Terima kasih

P粉707235568
P粉707235568

membalas semua(2)
P粉492959599

Dalam kes ini, memuatkan hubungan anda dengan penuh semangat boleh membantu.

$products = Product::whereBetween('id',[$num1,$num2])->with('get_note_voucher_lines')->get();
foreach($products as $product)
{
    $lines = $product->get_note_voucher_lines;
    // This should be faster and note that this is the right way to fetch laravel relation not as an array
}

Apa yang berlaku di sini ialah kami menggunakan jadual with() 方法在每次迭代中从 note_voucher_lines untuk pramuat 2k baris (dengan mengandaikan jadual produk anda mengandungi 2k baris) dan bukannya satu baris yang dimuatkan sebelum ini. Ini mengurangkan bilangan panggilan rangkaian yang dibuat ke pelayan pangkalan data, kini bukannya 300k panggilan, ia membuat 300k/2k panggilan.

Nota: Anda juga harus mempertimbangkan untuk menggunakan pemuatan blok untuk produk anda untuk mengelak daripada mencapai had memori apabila data anda terus berkembang. https://laravel.com/docs/10.x/eloquent#chunking-results

P粉244730625

Sebab utama kelewatan nampaknya adalah malas memuatkan hubungan get_note_voucher_lines.

Setiap kali anda mengakses perhubungan ini dalam gelung, Laravel akan membuat pertanyaan berasingan untuk mendapatkan baris yang berkaitan. Inilah yang dipanggil masalah N+1.

Untuk mengurangkan perkara ini, gunakan pemuatan bersemangat:

$products = Product::whereBetween('id',[$num1,$num2])->with('get_note_voucher_lines')->get();

Anda juga boleh menggunakan chunking untuk memproses data besar:

Product::whereBetween('id',[$num1,$num2])->with('get_note_voucher_lines')->chunk(100, function ($products) {
foreach ($products as $product) {

     $lines = $product->get_note_voucher_lines;
}});

Pastikan terdapat indeks pada medan id. Anda menyebut mempunyai indeks, tetapi pastikan ia adalah indeks yang betul dan bukan hanya kekangan kunci asing.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan