i have this model called Product
and i have model called Note_voucher_line
and this is relation inside product
public function get_note_voucher_lines()
{
return $this->hasMany('AppModelsNote_voucher_line','product_id','id')->orderBy('date','asc')->orderBy('note_voucher_id','asc');
}
now sometimes i have to loop products like this code
$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
}
the model Note_voucher_line
has over than 300k rows
and i have index on the migration
and this is the index migration inside note_voucher_lines
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');
});
there is index called product_id belong to products table
any help here to make it faster
thanks
2
Answers
Eager-loading your relationship can be helpful in this case.
What happens here is that we used the
with()
method to preload 2k rows from thenote_voucher_lines
table (assuming your products table contains 2k rows) in each iteration as opposed to one row that gets loaded previously. This reduces the number of network calls made to the database server so that instead of making 300k calls, it now makes 300k/2k calls.Note: you should also consider using chunk loading for your products to avoid hitting memory limits as your data continues to grow.
https://laravel.com/docs/10.x/eloquent#chunking-results
If you don’t need to process all 300k+ rows of note_voucher_lines at once, consider implementing pagination in your code. This way, you can fetch and process a limited number of records at a time, which can greatly improve performance.
Ensure that your database server is properly tuned for performance. This includes setting appropriate memory and buffer sizes, optimizing queries, and regularly maintaining your database (e.g., cleaning up unused data, rebuilding indexes).
If the data doesn’t change frequently, consider implementing caching mechanisms to store the results of expensive queries temporarily. This can significantly reduce the load on your database.