Featured image of post การจัดเก็บสกุลเงินในฐานข้อมูล: ควรใช้ DECIMAL หรือ BIGINT?

การจัดเก็บสกุลเงินในฐานข้อมูล: ควรใช้ DECIMAL หรือ BIGINT?

เมื่อพัฒนาระบบการชำระเงิน ควรใช้ฟิลด์ประเภทใดสำหรับสกุลเงิน? บทความนี้อธิบายว่าทำไมคุณถึงไม่ควรใช้ FLOAT อย่างเด็ดขาด และวิธีเลือกระหว่าง DECIMAL กับ BIGINT เพื่อสร้างระบบการจัดเก็บสกุลเงินที่ไม่มีข้อผิดพลาดและมีประสิทธิภาพสูง

เมื่อพัฒนาระบบการชำระเงินหรืออีคอมเมิร์ซ คุณเคยคิดจะใช้ FLOAT หรือ DOUBLE สำหรับ ฟิลด์จำนวนเงินในฐานข้อมูล หรือไม่?

ถ้าเคย หยุดความคิดนั้นไว้เลย! ระบบของคุณอาจกำลังแอบทำเงินรั่วไหลอยู่

ทำไมระบบการเงินจึงห้ามใช้จุดทศนิยม (floating-point)? ข้อผิดพลาดด้านความแม่นยำ ที่ดูเหมือนจะเล็กน้อย เมื่อสะสมไปตามปริมาณธุรกรรมมหาศาลและเวลาที่ผ่านไป อาจนำไปสู่ความหายนะที่ไม่อาจแก้ไขได้

แล้วเราควรใช้อะไรในการจัดเก็บเงินกันแน่?

ทำไม FLOAT จึงเป็นอันตรายต่อระบบการเงิน?

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

ตัวอย่างที่คลาสสิกที่สุดคือ: 0.1 + 0.2 มักจะไม่เท่ากับ 0.3 ในคอมพิวเตอร์ หากคุณต้องประมวลผลธุรกรรมหลายล้านรายการ ข้อผิดพลาดเล็กๆ น้อยๆ ระดับ “0.00000000000000004” เหล่านี้จะสะสมไปเรื่อยๆ และบัญชีก็จะไม่มีวันตรงกัน โปรดจำไว้ว่า:

เมื่อเป็นเรื่องของเงิน การใช้ “ค่าประมาณ” ใดๆ ล้วนนำมาซึ่งความหายนะ

บัญชีรายรับรายจ่ายสุดประณีตของนักบัญชี: ข้อดีของ DECIMAL

หากคุณต้องการโซลูชันที่แม่นยำแบบ “เห็นอย่างไร ได้อย่างนั้น” DECIMAL คือ ตัวเลขทศนิยมแบบคงที่ (fixed-point number) ที่ฐานข้อมูลรองรับตั้งแต่ต้น และเป็นมาตรฐานของอุตสาหกรรม

DECIMAL เปรียบเสมือนบัญชีรายรับรายจ่ายสุดประณีตในมือของนักบัญชี มันแยกจำนวนเต็มและทศนิยมออกจากกันอย่างแม่นยำ มั่นใจได้ว่า 0.1 + 0.2 จะเท่ากับ 0.3 อย่างแน่นอน

สัดส่วนทองคำของอุตสาหกรรม: DECIMAL(19, 4)

โดยปกติเรามักจะแนะนำให้ใช้ DECIMAL(19, 4):

  • 19: หมายถึงความสามารถในการรองรับตัวเลขทั้งหมด 19 หลัก (ความแม่นยำ)
  • 4: หมายถึงการเก็บตัวเลขหลังจุดทศนิยม 4 หลัก

ทำไมต้องเก็บทศนิยม 4 ตำแหน่ง? เพราะในระหว่างการคำนวณดอกเบี้ย อัตราภาษี หรืออัตราแลกเปลี่ยน ขั้นตอนกลางมักจะให้ผลลัพธ์ที่มีทศนิยมมากกว่า 2 ตำแหน่ง การสำรองตัวเลขบัฟเฟอร์ไว้ 2 หลักจะช่วยเพิ่มความแม่นยำในการคำนวณ และคุณสามารถปัดเศษตามความต้องการทางธุรกิจในขั้นตอนสุดท้ายได้อย่างง่ายดาย

พื้นที่ความจุขนาดนี้ มากพอที่จะให้คุณซื้อ GDP ทั้งหมดของโลกได้หลายใบเลยทีเดียว!

เพียงพอสำหรับสถานการณ์ทางการเงินในโลกแห่งความเป็นจริงหรือไม่?

ยกตัวอย่าง DECIMAL(19, 4):

  • ตัวเลขจำนวนเต็ม: 15 หลัก
  • จำนวนเงินสูงสุด: 999,999,999,999,999
  • แปลงเป็น USD: ประมาณ 999 ล้านล้านดอลลาร์สหรัฐ
ข้อมูลอ้างอิง จำนวนเงิน
GDP สหรัฐอเมริกา ประมาณ 27 ล้านล้านดอลลาร์สหรัฐ
GDP โลกรวม ประมาณ 105 ล้านล้านดอลลาร์สหรัฐ
ความมั่งคั่งโลกรวม ประมาณ 454 ล้านล้านดอลลาร์สหรัฐ

DECIMAL(19, 4) สามารถรองรับตัวเลขที่เกินกว่าความมั่งคั่งมวลรวมของโลกไปมาก ซึ่งเพียงพออย่างสมบูรณ์แบบสำหรับระบบการเงินส่วนใหญ่

ข้อจำกัดความแม่นยำ DECIMAL สูงสุดที่รองรับโดยฐานข้อมูลหลัก

ฐานข้อมูล ความแม่นยำสูงสุด (Precision)
MySQL / MariaDB 65
PostgreSQL 131072 (หลักจำนวนเต็ม) + 16383 (หลักทศนิยม)
SQL Server 38
Oracle 38

เครื่องเหรียญโทเค็นในอาเขต: วิธีหน่วยย่อยที่สุด BIGINT

หากคุณต้องการประสิทธิภาพขั้นสุด หรือระบบของคุณมีความต้องการทำงานพร้อมกันสูงมากอย่าง Stripe หรือ Alipay ดังนั้น BIGINT (วิธีการเก็บเป็นจำนวนเต็ม) อาจเป็นตัวเลือกที่ดีที่สุดของคุณ

วิธีการนี้เปรียบเสมือนเครื่องเหรียญโทเค็นในร้านเกมอาเขต: ไม่ว่าคุณจะใส่เงินเข้าไปเท่าไร เครื่องจะแปลงมันเป็น “หน่วยที่เล็กที่สุด” เพื่อใช้ในการจัดเก็บ ตัวอย่างเช่น:

  • $100.50 USD → จัดเก็บเป็น 10050 (เซนต์)
  • 100 TWD → จัดเก็บเป็น 100 (ดอลลาร์)

ทำไมต้องเลือก BIGINT?

เหตุผล คำอธิบาย
ความเร็วสูงมาก การบวกลบจำนวนเต็มคืองานที่ CPU ถนัด ประสิทธิภาพการคำนวณมักจะเร็วกว่า DECIMAL มาก
ประสิทธิภาพพื้นที่ จัดสรรพื้นที่คงที่ 8 ไบต์ เหมาะอย่างยิ่งสำหรับฐานข้อมูลขนาดใหญ่พิเศษ

อย่างไรก็ตาม ข้อเสียคือ อ่านยากกว่า เมื่อคุณเปิดฐานข้อมูลขึ้นมาและเห็นค่า 10050 คุณต้องรับหน้าที่หารด้วย 100 ภายในสมองของคุณ (หรือในโค้ดของคุณ) เองโดยอัตโนมัติ

บทสรุปสุดท้าย: ควรเลือกอย่างไร?

เพื่อตัดสินใจว่าจะใช้อะไร เราสามารถพิจารณาจาก “ความถี่ในการสืบค้นข้อมูล” และ “ขนาดของระบบ”:

มิติการเปรียบเทียบ DECIMAL BIGINT
ความสามารถในการอ่าน ยอดเยี่ยม (อ่านตัวเลขได้โดยตรง) แย่กว่า (ต้องแปลงค่าด้วยตนเอง)
ความเร็วในการคำนวณ ระดับปกติ เร็วมาก
สถานการณ์การใช้งาน ERP, ระบบการเงินภายใน, อีคอมเมิร์ซทั่วไป การซื้อขายความถี่สูง (HFT), ไมโครเซอร์วิสขนาดใหญ่พิเศษ, API สไตล์ Stripe

คำแนะนำในเชิงปฏิบัติ

สถานการณ์การใช้งาน ฟิลด์ที่แนะนำ
อีคอมเมิร์ซทั่วไป, ระบบรายงานข้อมูลภายในองค์กร ซึ่งนักบัญชีต้องรันคำสั่ง SQL เพื่อตรวจสอบบัญชีโดยตรง DECIMAL(19, 4)
ระบบการซื้อขายความถี่สูง (HFT) หรือความต้องการด้านความสามารถในการขยายระบบสูงสุด BIGINT

บทสรุป

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

All rights reserved,未經允許不得隨意轉載
ถูกสร้างด้วย Hugo
ธีม Stack ออกแบบโดย Jimmy