𝗦𝘁𝗼𝗽 𝗡+𝟭 𝗔𝘃𝗮𝗹𝗮𝗻𝗰𝗵𝗲𝘀: 𝗘𝗻𝗳𝗼𝗿𝗰𝗲 𝗟𝗮𝗿𝗮𝘃𝗲𝗹 𝗦𝘁𝗿𝗶𝗰𝘁 𝗠𝗼𝗱𝗲

ปัญหา N+1 query ทำลายประสิทธิภาพของฐานข้อมูล สิ่งนี้เกิดขึ้นเมื่อคุณดึงรายการข้อมูลออกมาแล้ววนลูปเพื่อเข้าถึงความสัมพันธ์ (relationship) โดยที่คุณลืมโหลดความสัมพันธ์นั้นไว้ล่วงหน้า

สมมติว่าคุณแสดงใบแจ้งหนี้ (invoices) 50 รายการบนแดชบอร์ด คุณวนลูปเพื่อแสดงชื่อลูกค้า แต่คุณลืมใช้ method with ผลที่ตามมาคือ Eloquent จะรัน 1 query เพื่อดึงใบแจ้งหนี้ และจากนั้นจะรันอีก 50 query แยกกันเพื่อดึงข้อมูลลูกค้าแต่ละราย

ในการพัฒนาบนเครื่อง local การรัน 51 query อาจใช้เวลาเพียง 10 มิลลิวินาที ซึ่งคุณจะไม่รู้สึกถึงความแตกต่าง แต่ในสภาพแวดล้อม production เมื่อมี traffic จำนวนมาก สิ่งนี้จะกลายเป็นหายนะ มันจะดึงทรัพยากรจาก database connection pool จนหมดและทำให้เซิร์ฟเวอร์ของคุณล่ม

คุณไม่สามารถพึ่งพาเพียงแค่การทำ code review ได้เท่านั้น แต่คุณต้องการเกราะป้องกันในระดับสถาปัตยกรรม (architectural guardrail)

Laravel มี Strict Mode เพื่อแก้ปัญหานี้ คุณสามารถใช้ preventLazyLoading ในระดับแอปพลิเคชันได้ โดย Laravel จะคอยตรวจสอบความสัมพันธ์ของฐานข้อมูล หากตรวจพบการทำ lazy load ในระหว่างการพัฒนาบนเครื่อง local หรือระหว่างการทดสอบ (testing) ระบบจะโยน exception ออกมา ซึ่งจะบังคับให้คุณต้องแก้ไขโค้ดในทันที

วิธีการตั้งค่า:

ตั้งค่ากลไกความปลอดภัยใน AppServiceProvider ของคุณ โดยทำสิ่งนี้สำหรับสภาพแวดล้อม local และ testing ส่วนใน production คุณควรใช้วิธีการ log error แทนที่จะปล่อยให้แอปพลิเคชันล่ม

ใช้การตั้งค่าทั้งสามนี้ใน method boot:

  • Model::preventLazyLoading: หยุดปัญหา N+1 queries
  • Model::preventSilentlyDiscardingAttributes: หยุดความล้มเหลวจากการทำ mass assignment
  • Model::preventAccessingMissingAttributes: หยุดปัญหา memory leaks ที่เกิดจากความสัมพันธ์ที่ขาดหายไป

สำหรับ production ให้ใช้ handleLazyLoadingViolationUsing ซึ่งจะช่วยให้คุณสามารถ log การละเมิดกฎเหล่านี้ไปยัง Slack หรือบริการ logging อื่นๆ ได้ วิธีนี้จะช่วยให้คุณมองเห็นปัญหาได้โดยไม่กระทบต่อประสบการณ์การใช้งานของผู้ใช้

การบังคับใช้ Strict Mode จะช่วยย้ายขั้นตอนการทำ optimization มาไว้ที่จุดเริ่มต้นของ pipeline ของคุณ ปัญหา N+1 queries จะไม่สามารถผ่านการทดสอบของคุณไปได้ ทำให้ codebase ของคุณได้รับการปรับแต่งให้เหมาะสมอยู่เสมอ และฐานข้อมูลของคุณจะทำงานได้อย่างรวดเร็ว

ที่มา: https://dev.to/iprajapatiparesh/stop-n1-avalanches-enforce-laravel-strict-mode-2oop