เทคนิคการเขียนโค้ดและปรับแต่ง Odoo ให้รองรับการใช้งานระดับองค์กรแบบมือโปร

10 นาที 14 views บันทึกเป็น PDF
เทคนิคการเขียนโค้ดและปรับแต่ง Odoo ให้รองรับการใช้งานระดับองค์กรแบบมือโปร

ทำไม Odoo ถึงอืดเมื่อข้อมูลเยอะ? มาเรียนรู้วิธีเขียนโค้ดและปรับแต่งฐานข้อมูล (Database) เพื่อให้ระบบ ERP ของคุณทำงานได้เร็วแรง รองรับผู้ใช้งานจำนวนมากได้จริง

ทำไม Odoo ถึงเริ่มช้าเมื่อมีข้อมูลเยอะ

เวลาเราเขียนโปรแกรมใน Odoo Implementation Services (บริการติดตั้งและวางระบบ Odoo) เรามักเริ่มจากข้อมูลหลักสิบแถว ซึ่งมันทำงานได้เร็วมากจนน่าตกใจ แต่พอเอาไปใช้จริงในบริษัทที่มีรายการสินค้าเป็นหมื่น หรือมีพนักงานกดใช้งานพร้อมกันหลายร้อยคน โปรแกรมกลับอืดเป็นเต่าคลาน ปัญหาคอขวด (จุดที่ทำให้ระบบทำงานต่อไม่ได้เพราะติดขัด) มักไม่ได้เกิดจากตัว Odoo เอง แต่เกิดจากวิธีที่เราเขียนโค้ดและตั้งค่าเซิร์ฟเวอร์

ลองนึกภาพว่าคุณมีพนักงานส่งของหนึ่งคน ถ้าต้องส่งของแค่ 2 ชิ้น เขาก็วิ่งไปส่งได้สบาย แต่ถ้าต้องส่ง 1,000 ชิ้นในเวลาเดียวกัน เขาจะสติแตกและทำงานช้าลง นี่คือสิ่งที่เกิดขึ้นกับฐานข้อมูล ถ้าเราเขียนคำสั่งให้ระบบวิ่งไปหยิบข้อมูลทีละชิ้นเหมือนคนส่งของคนนั้น ระบบก็ต้องเสียเวลาเดินทางไปกลับฐานข้อมูลเป็นพันรอบ แทนที่จะหยิบไปทีเดียวเป็นก้อนใหญ่

การวางระบบ Odoo ให้รองรับการใช้งานระดับองค์กรจึงไม่ใช่แค่การกดติดตั้งแล้วจบไป แต่มันคือวิศวกรรมซอฟต์แวร์ที่ต้องมองเห็นภาพรวม ทั้งเรื่องการเขียนโค้ด การจัดการฐานข้อมูล และการตั้งค่าเครื่องเซิร์ฟเวอร์ให้เหมาะสม ถ้าเราวางรากฐานไม่ดีตั้งแต่ต้น พอข้อมูลเยอะขึ้น การจะกลับมาแก้ไขให้เร็วเท่าเดิมนั้นทำได้ยากและเสียค่าใช้จ่ายสูงมาก

วางแผนก่อนเริ่ม: เข้าใจพฤติกรรมผู้ใช้งาน

ก่อนจะเขียนโค้ดบรรทัดแรก คุณต้องตอบให้ได้ก่อนว่าระบบของคุณจะมีคนใช้กี่คน และพีคสุดๆ (ช่วงเวลาที่มีคนใช้เยอะที่สุด) จะมีข้อมูลวิ่งเข้ามากแค่ไหน การเดาสุ่มด้วยการอัดสเปกเครื่องสูงๆ ตั้งแต่แรกไม่ใช่คำตอบ เพราะถ้าโค้ดเราแย่ ต่อให้ซื้อเซิร์ฟเวอร์ราคาหลักล้านมา ระบบก็ยังช้าอยู่ดี

เราต้องจำแนกประเภทงานให้ชัดเจน เช่น งานไหนที่ผู้ใช้ต้องรอผลทันที (เช่น การกดบันทึกใบเสนอราคา) และงานไหนที่ปล่อยให้ทำงานเบื้องหลังได้ (เช่น การส่งอีเมลแจ้งเตือน) การแยกงานเหล่านี้ออกจากกันจะช่วยให้เราออกแบบระบบได้แม่นยำขึ้น ว่าควรใช้ทรัพยากรตรงไหนมากหรือน้อย

สิ่งสำคัญคือการกำหนดค่า Baseline (ค่ามาตรฐานอ้างอิง) เพื่อวัดว่าระบบที่เร็วคือแค่ไหน เช่น หน้าจอหลักต้องโหลดเสร็จภายใน 2 วินาที หรือการทำรายการขายต้องไม่เกิน 3 วินาที ถ้าเราไม่มีตัวเลขเหล่านี้ในใจ เราจะไม่มีวันรู้เลยว่าระบบที่ทำอยู่นั้น "เร็วพอ" สำหรับการใช้งานจริงในบริษัทแล้วหรือยัง

Profiling: ตามหาจุดที่ทำให้ระบบช้า

Profiling (การตรวจสอบประสิทธิภาพการทำงานของโค้ด) คือขั้นตอนการดูว่าโปรแกรมของเราเสียเวลาไปกับตรงไหนมากที่สุด Odoo มีเครื่องมือในตัวที่ช่วยบอกได้ว่า คำสั่งไหนใช้เวลานาน หรือคำสั่งไหนที่เรียกซ้ำไปซ้ำมาโดยไม่จำเป็น การเดาเอาเองว่าส่วนไหนช้าเป็นนิสัยที่มือใหม่มักทำ และมักจะแก้ผิดจุดเสมอ

ขั้นตอนการทำ Profiling เริ่มจากการจำลองสถานการณ์ที่มีข้อมูลเยอะจริงๆ แล้วรันระบบในโหมดตรวจสอบ เพื่อดูว่าฐานข้อมูลทำงานหนักแค่ไหน และโค้ด Python (ภาษาที่ใช้เขียน Odoo) ของเราหน่วงตรงไหน ผลลัพธ์ที่ได้จะบอกเราชัดเจนว่าควรไปแก้ที่ SQL (ภาษาสำหรับสั่งงานฐานข้อมูล) หรือแก้ที่ Logic (ตรรกะการทำงาน) ในโปรแกรม

ตัวอย่างเช่น การดึงข้อมูลในลูป (การทำงานซ้ำๆ) คือตัวการหลักที่ทำให้ระบบช้า แทนที่จะเขียนโค้ดให้ระบบไปถามฐานข้อมูลทุกครั้งที่วนลูป เราควรเปลี่ยนเป็นการดึงข้อมูลออกมาทั้งหมดในครั้งเดียวแล้วค่อยเอามาจัดการในหน่วยความจำแทน วิธีนี้จะลดการวิ่งไปกลับระหว่างโปรแกรมกับฐานข้อมูลได้มหาศาล

# แบบที่ผิด: ดึงข้อมูลทีละบรรทัดในลูป ทำให้ฐานข้อมูลทำงานหนัก
for email in emails:
    partner = self.env["res.partner"].search([("email", "=", email)])
    # โค้ดส่วนนี้จะสั่งฐานข้อมูลทุกครั้งที่วนลูป

# แบบที่ถูก: ดึงข้อมูลออกมาเป็นก้อนเดียว แล้วค่อยนำมาค้นหา
partners = self.env["res.partner"].search([("email", "in", emails)])
partner_map = {p.email: p for p in partners}
for email in emails:
    partner = partner_map.get(email)
    # ฐานข้อมูลทำงานแค่ครั้งเดียวตอน search

ในตัวอย่างแรก ระบบจะสั่งฐานข้อมูลตามจำนวนอีเมล ถ้ามี 1,000 อีเมล ก็ต้องสั่งฐานข้อมูล 1,000 ครั้ง ส่วนตัวอย่างที่สองเราดึงข้อมูลมาเก็บไว้ใน partner_map (ตัวแปรเก็บข้อมูลแบบคู่คีย์) ก่อน แล้วค่อยเอามาใช้ ทำให้ฐานข้อมูลทำงานแค่ครั้งเดียว ผลลัพธ์ที่ได้คือความเร็วที่เพิ่มขึ้นหลายเท่าตัวเมื่อข้อมูลมีปริมาณมาก

ปรับแต่งฐานข้อมูลและ ORM ให้ทำงานร่วมกัน

ORM (ตัวกลางที่ช่วยให้เราเขียนคำสั่ง Python แทนภาษา SQL) เป็นเครื่องมือที่สะดวกมาก แต่ถ้าใช้ไม่เป็น มันจะสร้างคำสั่งที่ไร้ประสิทธิภาพออกมา ฐานข้อมูลอย่าง PostgreSQL ต้องการดัชนี หรือ Index (สารบัญฐานข้อมูล) เพื่อให้ค้นหาข้อมูลได้เร็วขึ้นเหมือนการเปิดดัชนีหลังหนังสือแทนการไล่อ่านทีละหน้า

การใส่ Index ทุกช่องที่ค้นหาได้ไม่ใช่เรื่องดีเสมอไป เพราะทุกครั้งที่คุณเพิ่มหรือแก้ไขข้อมูล ระบบต้องเสียเวลาอัปเดต Index เหล่านั้นด้วย ดังนั้นเราต้องเลือกใส่เฉพาะฟิลด์ที่ถูกเรียกใช้งานบ่อยๆ จริงๆ เช่น รหัสสินค้า หรือสถานะของใบสั่งซื้อ เพื่อให้สมดุลระหว่างความเร็วในการอ่านและความเร็วในการบันทึกข้อมูล

การออกแบบตารางข้อมูลต้องคำนึงถึงขนาดของข้อมูลในอนาคตด้วย การใช้ Computed Fields (ช่องข้อมูลที่คำนวณจากค่าอื่น) แบบเก็บค่าไว้ในฐานข้อมูล (Stored) จะช่วยให้การดึงข้อมูลรายงานทำได้เร็วขึ้นมาก แต่ต้องแลกมาด้วยการที่ระบบต้องคำนวณใหม่ทุกครั้งที่มีการเปลี่ยนแปลงข้อมูลต้นทาง ต้องเลือกใช้ให้ถูกงานครับ

# การกำหนด index ใน field เพื่อให้ค้นหาได้เร็วขึ้น
status = fields.Selection(
    [("draft", "ร่าง"), ("done", "เสร็จสิ้น")],
    index=True, # บอกให้ระบบสร้างสารบัญสำหรับฟิลด์นี้
)

คำสั่ง index=True จะสั่งให้ฐานข้อมูลสร้างสารบัญสำหรับฟิลด์ status ทำให้เวลาเราเขียนคำสั่งค้นหาใบสั่งซื้อตามสถานะ ระบบจะกระโดดไปหาข้อมูลนั้นได้ทันทีโดยไม่ต้องไล่ตรวจดูข้อมูลทั้งตาราง ผลลัพธ์คือการแสดงผลหน้าจอรายการขายที่เร็วขึ้นอย่างเห็นได้ชัด

การตั้งค่า Worker ให้เหมาะกับเครื่อง

Worker (กระบวนการทำงานที่ช่วยแบ่งเบาภาระใน Odoo) คือกุญแจสำคัญในการรองรับผู้ใช้งานพร้อมกันหลายคน การตั้งค่า Worker ไม่ใช่แค่การใส่ตัวเลขเยอะๆ ยิ่งใส่เยอะเกินไปจะทำให้เครื่องกินแรมจนค้างได้ เราต้องปรับค่าให้สอดคล้องกับจำนวน CPU และแรมที่มีอยู่จริงในเครื่องเซิร์ฟเวอร์

สำหรับระบบที่ใช้งานจริง เราต้องกำหนด Limit (ขีดจำกัด) ของหน่วยความจำให้ชัดเจน เพื่อป้องกันไม่ให้ Worker ตัวใดตัวหนึ่งกินแรมจนระบบล่มทั้งเซิร์ฟเวอร์ และควรเผื่อพื้นที่ไว้สำหรับ Cron Jobs (งานที่ตั้งเวลาให้ทำเองอัตโนมัติ) เพราะถ้าเราเปิดให้ Worker ทำงานหน้าเว็บจนเต็มหมด งานเบื้องหลังที่สำคัญจะไม่มีที่ยืนและค้างไปในที่สุด

การปรับแต่ง Worker ควรทำหลังจากที่เราปรับจูนโค้ดและฐานข้อมูลจนดีที่สุดแล้วเท่านั้น ถ้าโค้ดเรายังเขียนแบบวนลูปไร้ประสิทธิภาพ ต่อให้เพิ่ม Worker อีกกี่สิบตัว ก็แก้ปัญหาไม่ได้ เพราะตัวฐานข้อมูลเองนั่นแหละที่จะกลายเป็นคอขวดเพราะต้องรอรับคำสั่งที่ซ้ำซ้อนจาก Worker ทุกตัวที่รุมเข้ามาพร้อมกัน

# ตัวอย่างการตั้งค่าในไฟล์ odoo.conf
workers = 8 # จำนวนกระบวนการทำงาน
limit_memory_soft = 629145600 # เตือนเมื่อกินแรมเกิน 600MB
limit_memory_hard = 1677721600 # สั่งหยุดถ้ากินแรมเกิน 1.6GB
max_cron_threads = 1 # พื้นที่สำหรับงานเบื้องหลัง

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

สรุป: เปลี่ยนโปรเจกต์ติดตั้งให้เป็นงานวิศวกรรม

การเป็นโปรแกรมเมอร์ที่เก่ง Odoo ไม่ใช่แค่การติดตั้งโปรแกรมเป็น แต่คือการมองระบบให้ออกว่ามันทำงานอย่างไรภายใต้ฝากระโปรงรถ การออกแบบระบบให้รองรับ Production-Grade (มาตรฐานการใช้งานจริง) คือการผสมผสานระหว่างการเขียนโค้ดที่สะอาด การจัดการฐานข้อมูลที่ฉลาด และการตั้งค่าโครงสร้างพื้นฐานที่พอดี

จำไว้เสมอว่าการปรับจูนระบบคือการเดินทาง ไม่ใช่จุดหมาย ทุกครั้งที่คุณเพิ่มฟีเจอร์ใหม่หรือมีข้อมูลไหลเข้ามามากขึ้น คุณควรกลับมาตรวจสอบประสิทธิภาพอยู่เสมอ ใช้เครื่องมือ Profiling บ่อยๆ และอย่ากลัวที่จะแก้ไขโค้ดเก่าถ้ามันเริ่มช้าลง เพราะนั่นคือโอกาสที่คุณจะได้ฝึกฝนทักษะการแก้ปัญหาให้คมขึ้น

ตัวอย่างการนำไปใช้จริง: หากคุณกำลังทำระบบจัดการคลังสินค้า แล้วพบว่าหน้าจอเช็คสต็อกช้ามาก ให้เริ่มจาก (1) เปิดตัว Profiler ดูว่าคำสั่งไหนช้า (2) ตรวจสอบว่าในโค้ดมีการวนลูปดึงข้อมูลหรือไม่ (3) เพิ่ม Index ให้กับฟิลด์ที่ใช้ค้นหาสินค้าบ่อยๆ เพียงเท่านี้คุณก็จะเห็นความแตกต่างที่ชัดเจน และเป็นการสร้างนิสัยการทำงานแบบวิศวกรซอฟต์แวร์มืออาชีพครับ


ที่มา: How to Design Odoo Implementation Services for Production-Grade ERP Performance — DEV Community

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

เทคนิคเขียนแอป Flutter สำหรับ Meta Smart Glasses ให้ลื่นไหลและมีประสิทธิภาพ

เทคนิคเขียนแอป Flutter สำหรับ Meta Smart Glasses ให้ลื่นไหลและมีประสิทธิภาพ

เรียนรู้วิธีเขียนแอป Flutter เชื่อมต่อ Meta Smart Glasses ให้ทำงานเร็ว ไม่กระตุก ด้วยการวางสถาปัตยกรรมโค้ดและการจัดการข้อมูลแบบมือโปรที่มือใหม่ทำตามได้จริง

ที่มา: DEV Community

3 hours ago 10 นาที
5 views
เปรียบเทียบ WebSocket, SSE และ Polling เลือกวิธีทำระบบ Real-Time ให้เหมาะกับงาน

เปรียบเทียบ WebSocket, SSE และ Polling เลือกวิธีทำระบบ Real-Time ให้เหมาะกับงาน

อยากทำระบบ Real-Time แต่ไม่รู้จะเลือกใช้ Polling, SSE หรือ WebSocket ดี? มาดูวิธีเลือกใช้ให้เหมาะกับงาน เพื่อให้แอปของคุณทำงานลื่นไหลและประหยัดทรัพยากรเซิร์ฟเวอร์

ที่มา: DEV Community

7 hours ago 10 นาที
4 views