ບັນຫາ N+1 Query

ບັນຫາ N+1 Query ແມ່ນຮູບແບບຕ້ານປະສິດທິພາບ (anti-pattern) ດ້ານປະສິດທິພາບ ທີ່ເກີດຂຶ້ນເມື່ອດຶງຂໍ້ມູນລາຍການດ້ວຍ query ຄັ້ງດຽວ ແລ້ວຕາມດ້ວຍການດຶງຂໍ້ມູນທີ່ກ່ຽວຂ້ອງຂອງແຕ່ລະ record ທີລະລາຍການແຍກກັນ ສົ່ງຜົນໃຫ້ມີການເຂົ້າເຖິງຖານຂໍ້ມູນທັງໝົດ N+1 ຄັ້ງ.
"N" ແລະ "1" ໃນ N+1
ເມື່ອໃຊ້ ORM (Object-Relational Mapping) ຫຼື query builder, ມັກຈະເກີດບັນຫານີ້ໂດຍບໍ່ຮູ້ຕົວ. ຮູບແບບຂອງມັນເປັນດັ່ງນີ້:
- ດຶງລາຍການຈາກ parent table — ນີ້ຄືການ query ທີ່ເອີ້ນວ່າ "1"
- ສຳລັບແຕ່ລະລາຍການທີ່ດຶງໄດ້ N ລາຍການ, ສອບຖາມຂໍ້ມູນທີ່ກ່ຽວຂ້ອງຈາກ child table — ນີ້ຄື query ທີ່ເຮັດ "N" ຄັ້ງ
ຍົກຕົວຢ່າງ, ລອງຄິດເຖິງກໍລະນີທີ່ສະແດງໜ້າລາຍການຄຳສັບ. ທຳອິດ SELECT 50 ລາຍການຈາກ table glossaries, ຈາກນັ້ນດຶງຂໍ້ມູນການແປຂອງແຕ່ລະຄຳສັບຈາກ table translations ທີລະລາຍການ, ລວມແລ້ວຈະມີ query ທັງໝົດ 51 ຄັ້ງ. ຖ້າຈຳນວນລາຍການເພີ່ມເປັນ 500, ກໍຈະເຮັດ 501 ຄັ້ງ.
ເປັນຫຍັງຈຶ່ງຮ້າຍແຮງ
ເຖິງແມ່ນວ່າແຕ່ລະ query ຈະຕອບສະໜອງພາຍໃນໄລຍະສອງສາມ millisecond, ແຕ່ເນື່ອງຈາກຈຳນວນຄັ້ງເພີ່ມຂຶ້ນແບບ linear, response time ຈຶ່ງຊຸດໂຊມລົງຕາມສັດສ່ວນຂອງປະລິມານຂໍ້ມູນ. table ທີ່ໃນ local development ມີພຽງສອງສາມສິບລາຍການ ອາດຂະຫຍາຍເປັນຫຼາຍພັນລາຍການໃນ production ແລ້ວຄ່ອຍສະແດງໃຫ້ເຫັນຄວາມຊ້າ — ອຸບັດຕິເຫດແບບນີ້ບໍ່ແມ່ນເລື່ອງແປກ.
ຍິ່ງໄປກວ່ານັ້ນ, ໃນສະພາບແວດລ້ອມທີ່ DB server ແລະ application server ຖືກແຍກອອກຈາກກັນຜ່ານ network, 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 ໂດຍການ join ໃນ query ດຽວ |
| DataLoader pattern | DataLoader ຂອງ GraphQL / cache() ຂອງ Next.js | ລວບລວມ key ພາຍໃນ request ແລ້ວປ່ຽນເປັນ batch query |
ໃນກໍລະນີທີ່ໃຊ້ Supabase, ການໃຊ້ embedded query ຂອງ PostgREST (select("*, translations(*)")) ຊ່ວຍໃຫ້ດຶງຂໍ້ມູນທີ່ກ່ຽວຂ້ອງໄດ້ໃນ 1 request ໂດຍບໍ່ຕ້ອງຂຽນ loop ຢູ່ຝ່າຍ application.
ການກວດຫາ ແລະ ການປ້ອງກັນ
ເພື່ອກວດຫາ N+1 ໃນຂັ້ນຕອນການພັດທະນາ, ການຕິດຕາມ query log ແມ່ນມີປະສິດທິພາບ. ສຳລັບ PostgreSQL, ສາມາດຕັ້ງ log_min_duration_statement ເປັນ 0 ເພື່ອ log query ທັງໝົດ, ແລ້ວກວດສອບວ່າມີ query ທີ່ມີຮູບແບບດຽວກັນຕໍ່ເນື່ອງກັນຫຼືບໍ່. ສຳລັບ Rails ມີ bullet gem, ສຳລັບ Django ມີ django-debug-toolbar ເປັນເຄື່ອງມືກວດຫາ.
ພຽງແຕ່ໃສ່ໃຈໃນຂັ້ນຕອນ code review ວ່າ "ມີ await ຢູ່ພາຍໃນ loop ຫຼືບໍ່", ກໍສາມາດປ້ອງກັນ N+1 ໄດ້ຫຼາຍກໍລະນີ.
ບົດຄວາມທີ່ກ່າວເຖິງຄຳສັບນີ້
- ການນຳໃຊ້ AI Observability: ການເຊື່ອມໂຍງກັບການຕິດຕາມແອັບພລິເຄຊັນທີ່ມີຢູ່ ແລະ ການນຳໃຊ້ແບບເປັນຂັ້ນຕອນຂັ້ນຕອນການປະຕິບັດເພື່ອເຊື່ອມໂຍງ AI Observability ເຂົ້າກັບໂຄງສ້າງພື້ນຖານ ຫຼື Infrastructure ການຕິດຕາມແອັບພລິເຄຊັນ. ຮຽນຮູ້ວິທີສ້າງຂະບວນການ ຫຼື Pipeline ແລະຍຸດທະສາດການນຳໃຊ້.
- Adaptive RAG ແມ່ນຫຍັງ? ວິທີສ້າງຄວາມສົມດຸນລະຫວ່າງຕົ້ນທຶນ ແລະ ຄວາມແມ້ນຍຳດ້ວຍການຄົ້ນຫາແບບ Dynamic ທີ່ຂັບເຄື່ອນດ້ວຍ Query
- PoC Development ແມ່ນຫຍັງ? ຕັ້ງແຕ່ພື້ນຖານຂອງການພິສູດແນວຄິດ, ຄ່າໃຊ້ຈ່າຍ, ວິທີດຳເນີນການ ຈົນເຖິງການເລືອກຜູ້ຮັບເໝົາພາຍນອກທີ່ບໍ່ລົ້ມເຫລວອະທິບາຍພື້ນຖານ PoC, ລາຄາ, 5 ຂັ້ນຕອນ ແລະ ການເລືອກຜູ້ຮັບເໝົາ. ແນະນຳວິທີໃຊ້ AI ຫຼຸດໄລຍະທົດສອບ. Unimon ບາງກອກ ຮັບປຶກສາຟຣີ!
- ຖານຂໍ້ມູນ Vector ແມ່ນຫຍັງ? ຄູ່ມືຄົບຖ້ວນກ່ຽວກັບວິທີການເຮັດວຽກ, ການປຽບທຽບຜະລິດຕະພັນຊັ້ນນຳ, ແລະ ການນຳໃຊ້ RAGຈາກແນວຄິດພື້ນຖານຂອງ vector database ຈົນເຖິງການປຽບທຽບ Pinecone, Weaviate, ແລະ pgvector ລວມທັງການເຊື່ອມຕໍ່ RAG — ຄູ່ມືຊັດເຈນສຳລັບຜູ້ຈັດການ AI.
ຄຳສັບທີ່ກ່ຽວຂ້ອງ

ການທົດສອບ E2E
ການທົດສອບ E2E (End-to-End Testing) ແມ່ນວິທີການທົດສອບທີ່ເລີ່ມຕົ້ນຈາກການກະທຳຂອງຜູ້ໃຊ້ງານ ໂດຍຜ່ານ brows

ການທົດສອບການຮັບຮອງ
ການທົດສອບການຍອມຮັບ (Acceptance Test) ແມ່ນວິທີການທົດສອບທີ່ກວດສອບວ່າຟັງຊັນທີ່ພັດທະນາແລ້ວນັ້ນຕອບສະໜອງຄວ

SSM (AWS Systems Manager)
AWS Systems Manager (SSM) ແມ່ນ AWS Managed Service ທີ່ໃຊ້ສໍາລັບການດໍາເນີນງານ ແລະ ຈັດການ EC2 instance

ATDD
ATDD (Acceptance Test-Driven Development) ແມ່ນວິທີການພັດທະນາທີ່ທີມງານທັງໝົດກຳນົດເງື່ອນໄຂຂອງ acceptan



