نحوه جلوگیری از نمایش داده های N + 1 در PHP

من چند روز پیش در حال بررسی یک پایگاه کد Laravel بودم و یک اشتباه پرس و جو مشترک N+1 را دیدم. پرس و جو n+1 برنامه های ما را به طور ناآگاهانه کند می کند. از آنجا که چیزهایی که قرار است یکباره اجرا شوند 4 تا 5 بار اجرا می شوند.
من تأکید خواهم کرد دو نمونه های پرس و جو N+1 و راه حل (های) آنها.
سناریو یکی:
ما در حال تلاش برای ایجاد یک آرایه برای ایجاد معاملات در پایگاه داده هستیم.
اشتباه
foreach ($request->transactions as $transaction) {
Transaction::create([
"transactionId" => $transaction->id,
"amount" => $transaction->amount
// and the rest of the code
]);
}
این یک مورد کلاسیک از پرس و جو N+1 است زیرا شما برای هر بار که از طریق یک حلقه می روید ، یک رکورد جدید ایجاد می کنید ، و این باعث می شود برنامه شما یا هر مسیری که این عملکرد را فراخوانی می کند ، کند شود.
راه حل ساده برای این کار خواهد بود.
- قبل از خط حلقه Foreach یک آرایه خالی اعلام کنید.
- از طریق آرایه حلقه کنید و آماده شوید تا رکورد را در پایگاه داده وارد کنید.
- همه آن را به یکباره در پایگاه داده وارد کنید.
اجرای توضیحات.
قبل از خط حلقه Foreach یک آرایه خالی را اعلام کنید
$storeTransaction = [];
از طریق کد حلقه کنید و نحوه وارد کردن آن را آماده کنید
$now = now();
foreach ($request->transactions as $transaction) {
$storeTransaction[] = [
"transactionId" => $transaction->id,
"amount" => $transaction->amount,
"created_at" => $now(),
"updated_at" => $now(),
];
}
همه آن را به طور هم زمان در پایگاه داده وارد کنید
Transaction::insert($storeTransaction);
این رویکرد یک درج در پایگاه داده انجام می دهد. بنابراین به جای قرار دادن 10 – 15 بار ، تمام داده ها را به طور همزمان در پایگاه داده وارد کردید.
سناریو دو:
در صورت وجود ، شما یک عملکرد برای دریافت رکورد و به روزرسانی رکورد دارید.
اشتباه
public function updateTransactionStatus($id)
{
$transaction = Transactions::where('id', $id)->get();
if (!$transaction) {
return $this->errorResponseHelper('fail', 'Transaction not found', 404);
}
Transactions::where('id', $id)->update(['status' => 1]);
return $this->successResponseHelper('success', 'Transaction updated successfully', $transaction);
}
در حالی که این عملکرد خاص یا بلوک کد کار خود را به طور مؤثر انجام می دهد ، کارآمد نیست ، زیرا ما دو بار در حال واگذاری سوابق هستیم ، سپس یک تماس دیگر برای به روزرسانی ردیف/ضبط انجام می دهیم.
راه حل ساده برای این کار خواهد بود.
- رکورد را با استفاده از بدست آوردن کلمه کلیدی
- اگر رکورد وجود ندارد ، یک پیام خطا را برگردانید
- اگر وجود دارد ، فقط از مدل یا سابقه ای که قبلاً برای به روزرسانی رکورد تماس گرفته اید استفاده کنید.
public function updateTransactionStatus($id)
{
$transaction = Transactions::where('id', $id)->get();
if (!$transaction) {
return $this->errorResponseHelper('fail', 'Transaction not found', 404);
}
$transaction->update(['status' => 1]);
return $this->successResponseHelper('success', 'Transaction updated successfully', $transaction);
}
کاری که شما در اینجا انجام داده اید کشتن دو یا سه پرنده با یک سنگ است.
اگر بلوک های کد مانند این را در پایگاه کد خود دارید ، وقت آن است که کد خود را بهینه کنید.
برنامه نویسی مبارک!