ปัญหา N+1 Query คือ anti-pattern ด้านประสิทธิภาพที่เกิดขึ้นเมื่อดึงข้อมูลรายการด้วย query ครั้งเดียว แล้วตามด้วยการ query แยกทีละรายการเพื่อดึงข้อมูลที่เกี่ยวข้องของแต่ละ record ส่งผลให้เกิดการเข้าถึงฐานข้อมูลทั้งหมด N+1 ครั้ง
### "N" และ "1" ใน N+1 เมื่อใช้งาน ORM (Object-Relational Mapping) หรือ query builder มักเกิดปัญหานี้โดยไม่รู้ตัว กระบวนการเป็นดังนี้ 1. ดึงรายการจาก parent table — นี่คือ query ที่เป็น "1" 2. สำหรับแต่ละรายการจาก N รายการที่ได้มา ให้สอบถามข้อมูลที่เกี่ยวข้องจาก child table — นี่คือ query ที่รันซ้ำ "N" ครั้ง ลองพิจารณากรณีการแสดงหน้ารายการ glossary ก่อนอื่น SELECT 50 รายการจากตาราง `glossaries` จากนั้นดึงข้อมูลการแปลของแต่ละคำจากตาราง `translations` ทีละรายการ รวมแล้ว query จะรันทั้งหมด 51 ครั้ง หากจำนวนรายการเพิ่มเป็น 500 ก็จะรัน 501 ครั้ง ### เหตุใดจึงเป็นปัญหาร้ายแรง แม้ query แต่ละครั้งจะตอบสนองภายในไม่กี่มิลลิวินาที แต่เนื่องจากจำนวนครั้งเพิ่มขึ้นแบบ linear response time จึงแย่ลงตามสัดส่วนของปริมาณข้อมูล ในระหว่างการพัฒนาบนเครื่อง local ตารางอาจมีเพียงหลักสิบรายการ แต่ในระบบ production อาจพองตัวเป็นหลักพัน และความล่าช้าจะปรากฏให้เห็นเป็นครั้งแรกตรงนั้น — อุบัติเหตุแบบนี้ไม่ใช่เรื่องแปลก นอกจากนี้ ในสภาพแวดล้อมที่ DB server และ application server แยกกันผ่านเครือข่าย overhead ของ round trip จะสะสมตามจำนวนครั้ง แม้ query เองจะเบา แต่ network latency กลายเป็นปัจจัยหลักที่ครอบงำประสิทธิภาพ ### แนวทางการแก้ไข วิธีแก้ปัญหาที่เป็นตัวแทนแบ่งออกเป็น 2 ประเภทหลัก ได้แก่ **eager loading** (การโหลดล่วงหน้า) และ **JOIN** | วิธีการ | ตัวอย่าง framework | ภาพรวม | |------|----------------|------| | eager loading | `includes` ของ Rails / `select_related` ของ Django / `include` ของ Prisma | ORM สร้าง query สำหรับดึงข้อมูลที่เกี่ยวข้องรวมกันโดยอัตโนมัติ | | explicit JOIN | raw SQL / `.select("*, children(*)")` ของ Supabase | รวม parent และ child ใน query เดียวแล้วส่งคืน | | DataLoader pattern | DataLoader ของ GraphQL / `cache()` ของ Next.js | รวบรวม key ภายใน request แล้วแปลงเป็น batch query | เมื่อใช้ Supabase การใช้ประโยชน์จาก embedded query ของ PostgREST (`select("*, translations(*)")`) ช่วยให้ดึงข้อมูลที่เกี่ยวข้องได้ใน 1 request โดยไม่ต้องเขียน loop ในฝั่ง application ### การตรวจจับและการป้องกัน ในระหว่างการพัฒนา การตรวจสอบ query log เป็นวิธีที่มีประสิทธิภาพในการค้นหา N+1 สำหรับ PostgreSQL ให้ตั้งค่า `log_min_duration_statement` เป็น 0 เพื่อบันทึก query ทั้งหมด แล้วตรวจสอบว่ามี query ที่มีรูปแบบเดียวกันรันต่อเนื่องกันหรือไม่ สำหรับ Rails มี `bullet` gem และสำหรับ Django มี `django-debug-toolbar` เป็นเครื่องมือตรวจจับ เพียงแค่ตระหนักในขั้นตอน code review ว่า "มี `await` อยู่ภายใน loop หรือไม่" ก็สามารถป้องกัน N+1 ได้เป็นจำนวนมากก่อนที่จะเกิดปัญหา



A2A (Agent-to-Agent Protocol) คือโปรโตคอลการสื่อสารที่ช่วยให้ AI Agent ต่างชนิดสามารถค้นหาความสามารถ มอบหมายงาน และซิงโครไนซ์สถานะระหว่างกันได้ โดย Google เปิดตัวในเดือนเมษายน ปี 2025

Agentic AI คือชื่อเรียกรวมของระบบ AI ที่สามารถตีความเป้าหมาย และวางแผน ดำเนินการ รวมถึงตรวจสอบผลลัพธ์ได้อย่างอิสระโดยไม่ต้องรับคำสั่งทีละขั้นตอนจากมนุษย์

ATDD (Acceptance Test-Driven Development) คือวิธีการพัฒนาซอฟต์แวร์ที่ทีมงานทั้งหมดร่วมกันกำหนดเกณฑ์การทดสอบการยอมรับ (Acceptance Test) ก่อนเริ่มการพัฒนา จากนั้นจึงทำการ Automate การทดสอบดังกล่าว แล้วจึงดำเนินการ Implement ต่อไป

Claude Agent SDK คือชุดเครื่องมือพัฒนา (development kit) สำหรับสร้าง AI Agent ที่จัดทำโดย Anthropic ซึ่งเป็น framework สำหรับการพัฒนา Agent ที่ใช้ประโยชน์จาก Tool Use และการสนทนาแบบหลายรอบ (multi-turn conversation) ของ Claude ผ่านโค้ด Python และ TypeScript

Claude Code คือ AI Coding Agent ประเภท Terminal-based ที่พัฒนาโดย Anthropic ซึ่งเป็นเครื่องมือ CLI ที่สามารถทำความเข้าใจ Codebase แก้ไขโค้ด รันการทดสอบ และดำเนินการ Git ได้อย่างครบวงจรผ่านคำสั่งภาษาธรรมชาติ