cari

Rumah  >  Soal Jawab  >  teks badan

Optimumkan gelung foreach Laravel dengan 2k dan tingkatkan pengambilan semula hubungan daripada 200k untuk mengurangkan masa pelaksanaan

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粉707235568P粉707235568247 hari yang lalu461

membalas semua(2)saya akan balas

  • P粉492959599

    P粉4929595992024-03-31 12:05:45

    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

    balas
    0
  • P粉244730625

    P粉2447306252024-03-31 09:24:23

    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.

    balas
    0
  • Batalbalas