[Golang] ทำไม ORM ไม่ควรเป็นทางออกที่ดีที่สุด?
การใช้งาน Databaseโดยการใช้ ORM เข้ามาช่วย ทำให้ประสิทธิภาพในการ Query ข้อมูลช้าลงจริงรึเปล่า มาลองพิสูจน์กัน
สำหรับคนมีเวลาอ่านน้อย
- 🚀 ORM คือ การ map ระหว่าง ข้อมูลที่มีความสัมพันธ์ (Relational Database) ให้มาอยู่ในรูปแบบ Object-Oriented Language และ แปลงข้อมูลที่ในรูป Object-Oriented Language กลับไปเป็น ข้อมูลที่รูปแบบข้อมูลที่มีความสัมพัมธ์ (Relational Database)
- ⚡️จะมีการทดสอบความแตกต่างระหว่างการใช้งาน Package ORM กับ Package Not ORM ในเรื่องประสิทธิภาพของการทำงานระหว่าง App กับ Database ในเรื่องของความเร็วแบบไหนจะเร็วกว่ากัน
- ♻️ จากการทดสอบโดยการ Query ข้อมูลจากให้ใช้งาน Package ทั้งสองแบบพบว่า การให้งาน Package ในแบบ ที่ไม่ใช่ ORM มีความเร็วในการว่า Query กว่า Package ที่เป็นแบบ ORM
กด 🔖 (Bookmark) ไว้อ่านทีหลังกันได้ถ้าไม่มีเวลา
ใครอยากเข้าใจมากขึ้นเริ่มอ่านบทความนี้ได้เลย 👇🏻
ณ ออฟฟิศที่ยานเราจอดอยู่ 🚀
เรื่องมันเกิดขึ้นในวันหนึ่ง พี่ Panupak Vichaidit ได้รีวิว Code ของในส่วนของผม พบว่าในส่วนของ Repository ได้มี Comment หนึ่ง บอกประมาณว่า
การใช้งาน Packageในลักษณะของ ORMในโปรเจค ทำให้การใช้งานระหว่าง App กับ Database มีประสิทธิภาพน้อยกว่า การใช้งาน Packageในลักษณะของ Not ORM
วันนี้เลยจะมาเขียน Code ตัวอย่างการใช้งาน Raw Query vs ORM vs Not ORM ว่าจะมีความแตกต่างกันจริงหรือไม่ ไปดูกันครับ
มาเริ่มทดสอบกันครับ 👨🚀
เนื้อหาของบล็อกนี้จะมายกตัวอย่าง Code สำหรับการ Query ข้อมูลจาก Databaseโดยจะมีทั้ง type-raw query, type-safe ของ ORM และ type-safe แบบที่ไม่ใช้ ORM ที่มี logic เดียวกันเพียงแค่แตกต่างจากการนำ Package เข้ามาช่วยสำหรับการเขียน Query ข้อมูลจาก Database
เริ่มกันเลยครับเรามาดู Package ที่นำมาใช้งานกันก่อน
ส่วนของ type-raw query จะเลือกใช้ Package พื้นฐานของภาษา Go
สำหรับ type-safe ORM เจ้าของบล็อกจะเลือกให้ Package ที่จะนิยมใช้กันคือ GORM
สำหรับ type-safe ที่ไม่ใช้ลักษณะของ ORM เจ้าของบล็อกจะเลือกใช้ GO-JET
ทั้งสอง Packageโดยเลือกมาจากการแนะนำจากเว็บ Awesome Go
ในส่วนของ logic มีการใช้งาน database โดยใช้งาน postgres database โดยมีการ SELECT ข้อมูลทั้งหมด 500000 (rows) พร้อมจับเวลาการประมวลผล
มาเริ่มในส่วน Raw Query กันก่อนครับ
mkdir example-raw-query.go
มาดูผลทดสอบ Raw Query โดยใช้ Package พื้นฐานของภาษา Go กัน
go run main.go
จากการทดสอบทั้งหมด 3 ครั้งในการ select ข้อมูลทั้ง 500000 (rows)
ค่าเฉลี่ยของความเร็วในการประมวลผลคือ 1.04016838 second
มาเริ่มในส่วน Package ในที่เป็นลักษณะแบบ ORM กันต่อ
mkdir example-orm.go
มาดูผลทดสอบ ในแบบ ORM
go run main.go
จากการทดสอบทั้งหมด 3 ครั้งในการ select ข้อมูลทั้ง 500000 (rows)
ค่าเฉลี่ยของความเร็วในการประมวลผลคือ 3.226739554 second
มาเริ่มในส่วน Package ที่ไม่ใช้ลักษณะของ ORM กันต่อ
mkdir example-notorm.go
มาดูผลทดสอบ ในแบบที่ไม่ใช้ ORM
go run main.go
จากการทดสอบทั้งหมด 3 ครั้งในการ select ข้อมูลทั้ง 500000 (rows)
ค่าเฉลี่ยของความเร็วในการประมวลผลคือ 2.21162734 second
ต่อไปจะเป็นการทดสอบ Benchmark ในแต่ละ Package กัน
ส่วนของ Raw Query โดยใช้ Package database/sql ของภาษา Go
มาดูผลทดสอบกันครับ
go test -bench=BenchmarkRowQuerySlice
ส่วนของ Package GORM
go test -bench=BenchmarkORMSlice
มาต่อในส่วนของ GO-JET กัน
go test -bench=BenchmarkNotORMSlice
จะเห็นว่าจำนวนการทำงาน 1 รอบ โดยแต่ละรอบ Query ทั้งหมด 500000 (rows) base ใช้เวลา 1.200 วินาที ส่วน GORM ใช้เวลา 3.317 วินาที และ GO-JET ใช้เวลา 2.332 วินาที
สรุป
ในเรื่องของ Performance จะเห็นว่าแบบ Raw Query สามารถ query ข้อมูลได้เร็วที่สุดถ้าเทียบกับ type-safe orm โดยใช้ gorm กับ go-jet ถึงแม้ Raw Query จะมีความเร็วที่สุด ก็ยังมีข้อเสียในส่วนของการทำ Debug Code ที่ทำได้ยากกว่า type-safe SQL queries
และมีข้อดีในส่วนของการใช้ Package ที่ไม่อยู่ในรูปแบบของ ORM เจ้าของบล็อกคิดว่าการที่เราเลือกใช้ GO-JET มันทำให้เราเขียน Query ได้ใกล้เคียงภาษา SQL มากที่สุด ถือว่าเป็นข้อดีในการสะสมสกิลเพิ่มขึ้นได้ เพราะถ้าเรายังใช้ Package ORM สำหรับ 1 ภาษา ก็มี Package ORM อยู่จำนวนมาก แต่ละบริษัทก็เลือกใช้ ORM แตกต่างกันไป ทำให้เราต้องฝึกใช้ ORM ในแต่ละแบบอยู่ตลอด ซึ่งทำให้เราต้องเริ่มต้นใหม่อยู่เสมอ
นี่เป็นเพียงความคิดเห็นของผมเท่านั้น หากผิดพลาดประการใดก็ต้องขออภัย หวังว่าจะเป็นประโยชน์ต่อผู้ที่สนใจ ลองนำไปปรับใช้งานกันดูนะครับ