หัวใจที่สำคัญที่สุดของฐานข้อมูล

🤔 ความรู้เบื้องต้นของฐานข้อมูลที่โปรแกรมเมอร์ 90% ไม่รู้

😢 ปัญหา

ฐานข้อมูลที่ใช้อยู่ดีๆก็แปลงร่างเป็นเต่า ทำอะไรกับมันก็ช้า จัด index เคลียข้อมูล ทำ replica ต่างๆนานๆก็ดีขึ้นมาหน่อย ซักพักก็กลับไปเป็นเต่าตัวเดิมเลย แก้ไงดี?

circle-check

😄 วิธีแก้ปัญหา

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

circle-info

เรื่องตลกร้าย หลายคนที่ทำงานในวงการนี้แม้จะมีประสบการณ์ในการทำงานมาเป็น 10 ปี ออกแบบฐานข้อมูลมาได้เป็นอย่างดี รู้จัก database family ต่างๆ ก็อาจจะตกม้าตายเพราะแค่เรื่องพื้นฐานตัวนี้ก็ได้นะเชื่อไหม?

🤔 พื้นฐานที่สำคัญที่สุดคืออะไร ?

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

😫 นี่มันรูปบร้าไร ?

ผมขออธิบายเป็นแบบนี้ละกันว่า ไม่ว่าจะเป็นโปรแกรมบ้าบออะไรก็แล้วแต่ สุดท้ายมันก็จะมีแค่ ตัวแอพ ที่จะคอยเรียกใช้ ตัวฐานข้อมูล ใช่ป่ะ ดังนั้นมองรูปดีๆเราก็จะเห็นว่ามันแบ่งออกเป็น 2 ฝั่ง นั่นคือฝั่ง ตัวแอพ (App) กับฝั่ง ตัวฐานข้อมูล (DB) ยังไงล่ะ

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

ซึ่งตัวแอพมันก็จะบอกตัวฐานข้อมูลว่ามันอยากได้ข้อมูลอะไรบ้าง ดังนั้นตัวฐานข้อมูลก็จะต้องใช้ Computing power ไปไล่ดูดข้อมูลในตัวมันเอง ตามที่ตัวแอพขอมายังไงล่ะ

สีม่วงๆคือข้อมูลที่เก็บไว้ในฐานข้อมูล

หลังจากที่ตัวฐานข้อมูลได้ข้อมูลที่แอพขอมาละ มันก็จะทำการส่งข้อมูลพวกนั้นกลับไปให้ตัวแอพผ่านทาง Network ยังไงล่ะ ตามรูปด้านล่างเลย

สุดท้ายตัวแอพก็จะได้ข้อมูลมาไว้กับมัน แล้วมันก็จะเอาข้อมูลไปทำอะไรต่อก็แล้วแต่มันละ เช่นอาจจะเอาไปแสดงผลว่า มีรายการสินค้าอะไรบ้าง หรือ อาจจะเอาไปสร้างเป็นข้อมูลแบบอื่นก็ได้ ซึ่งมันก็จะใช้ Computing Power ในฝั่งของตัวแอพเองละ

ดังนั้นเราก็จะเห็นว่ามันมีข้อมูลทั้งหมด 3 แบบ

  1. สีม่วง (ขวาสุด) - คือข้อมูลดิบที่อยู่ในฐานข้อมูล

  2. สีน้ำเงิน (ตรงกลาง) - คือข้อมูลที่ส่งผ่าน network ระหว่างแอพกับฐานข้อมูล ซึ่งข้อมูลที่ส่งกลับจากฐานข้อมูลอาจจะเป็นตัวเดียวกับสีม่วง หรืออาจจะถูกดัดแปลงเป็นแบบอื่นก่อนส่งไปให้ก็ได้เหมือนกัน และข้อมูลที่รับส่งนี้ก็อาจจะเป็นการส่งจากแอพไปยังฐานข้อมูลได้เช่นกัน

  3. สีเขียว (ซ้ายสุด) - คือข้อมูลที่อยู่ในตัวแอพแล้ว ไม่มีความเกี่ยวข้องอะไรกับในฐานข้อมูลอีกต่อไป คิดง่ายๆว่ามันเป็นแค่ตัว copy เท่านั้นแหละ

circle-info

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

😫 แล้วมันสำคัญยังไงแฟร๊ะ ?

ใจเย็นแล้วลองนั่งวิเคราะห์รูปให้ดีๆดิ แล้วลองตอบคำถามด้านล่างนี้ดูนะ

🔥 Database Query

🤔 จะเกิดอะไรขึ้นถ้าเราสั่งให้ตัวฐานข้อมูลไปดึงข้อมูลแบบที่มันซับซ้อนมากๆและกินเวลานานๆ 😱 ตัวดูดข้อมูลของ database ก็จะทำงานหนัก และถ้ามีคำขอแบบนี้เข้ามามากๆมันก็จะทำให้มันทำงานต่อไม่ได้ เพราะงานเก่ามันยังทำไม่เสร็จ งานใหม่เลยต้องรอคิวกันไปเรื่อยๆ ทำให้เกิดสิ่งที่เรียกว่า Database Overloaded นั่นเอง

🔥 Network Latency

🤔 จะเกิดอะไรขึ้นถ้าตัวแอพขอข้อมูลจากตัวฐานข้อมูลเป็นแสนๆรายการเลย? 😱 ข้อมูลเป็นแสนๆรายการก็จะต้องถูกส่งผ่าน network กลับมายังไงล่ะ ซึ่งถ้าข้อมูลยิ่งเยอะเท่าไหร่ ตัวแอพก็จะต้องรอนานมากขึ้นเท่านั้น เพราะมันต้องรอโหลดข้อมูลพวกนั้นจาก network อ่ะดิ

🔥 App Resource

🤔 จะเกิดอะไรขึ้นถ้าเราเอาข้อมูลปริมาณเยอะๆมาทำงานที่ฝั่งแอพ? 😱 ตัวแอพมีทรัพยากรที่ค่อนข้างจำกัด เช่น Computing Power หรือ RAM ที่น้อยอยู่แล้ว ถ้าต้องทำงานกับข้อมูลที่เยอะๆก็อาจจะกระตุก พัง และล่วงลับดับขันธ์ไปในที่สุดนั่นเอง และ การจัดการกับหน้าตา UX ก็จะแย่ด้วยอ่ะดิ

😭 แล้วแก้ไงอ่ะ ?

หลักในการแก้ปัญหาเรื่องนี้นั้นสุดแสนจะง่าย แค่ทำ 3 เรื่องด้านล่างก็พอละ

  1. ลดงานตัวดูด - อย่าสั่งอะไรที่มันซับซ้อนมากๆไปให้มันทำ และตัวฐานข้อมูลจริงๆมันก็มีงานที่มันถนัดและไม่ถนัดด้วยนะ ดังนั้นงานที่มันไม่ถนัดก็ส่งไปให้แอพจัดการต่อก็พอ

  2. ลดข้อมูลที่ส่งผ่าน network - ตัวนี้พูดยากเพราะรายละเอียดมันเยอะ แต่หลักงง่ายๆคือส่งไปแค่เท่าที่จำเป็นต้องใช้ก็พอ และอาจจะใช้เทคนิคต่างๆเข้ามาช่วยก็ได้ เช่น การทำ paging ก็เป็นตัวเลือกที่ดีเหมือนกัน

  3. ลดงานฝั่งแอพ - ตัวนี้ก็พูดยากอีกตัว แต่หลักง่ายๆคืออย่าให้มันต้องทำงานกับข้อมูลเยอะๆ เช่น ถ้าถามว่าเว็บเรามีหนังทั้งหมดกี่เรื่อง แทนที่จะส่งรายการหนังทั้งหมดมาที่ตัวแอพเพื่อให้มันไปนับเอง เราก็แค่ส่งจำนวนหนังในฐานข้อมูลไปให้แอพซะก็สิ้นเรื่อง

จากที่ว่ามาทั้ง 3 ข้อ เราก็จะได้ข้อสรุปว่า เราควรจะให้การทำงานมันออกมาตามภาพด้านล่างนี้ต่างหาก

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

circle-info

คำแนะนำ เทคนิคในการจัดการเรื่องทั้ง 3 ตัวนี้มีเป็นกระบุงเลย ไปไล่หาอ่านเอาได้เลยไม่งั้นผมคงไม่ได้นอนแน่ๆ และแต่ละวิธีก็มีข้อดีข้อเสีย และอย่าลืมดูตามความเหมาะสมของแต่ละวิธีด้วยนะ มันไม่มียาครอบจักรวาลหรอก

circle-info

เกร็ดความรู้ งานที่ฐานข้อมูลถนัดคือคณิตศาสตร์เบื้องต้นยังไงล่ะ เช่น การนับจำนวน การหาค่าสูงสุด หาค่าต่ำสุด มากกว่า น้อยกว่า ค่าเฉลี่ย ผลรวม บลาๆ ไรพวกนี้ ดังนั้นงานอะไรที่ใช้เรื่องพื้นฐานพวกนี้ทำได้ ก็อาจจะให้ทำใน database เลยแล้วค่อยส่งแค่ผลลัพท์กลับมาก็ได้ มันจะได้ไม่เปลือง Database computing power มากนัก ข้อมูลที่ส่งผ่าน network ก็น้อย ตัว client ก็ทำงานสบาย วินๆทั้งสองฝ่าย

😢 ขอตัวอย่างหน่อยได้ไหม ?

สมมุติว่าในฐานข้อมูลเก็บ ข้อมูลสินค้า ข้อมูลลูกค้า และ บันทึกการสั่งสื้อสินค้าไว้ละกัน ซึ่งพอเขียน diagram ก็จะออกมาแบบนี้ (การสั่งซื้อแต่ละครั้งสั่งสินค้าได้ 1 ชนิดเท่านั้น) ตามรูปด้านล่างเบย

🤔 ถ้าอยากรู้ว่าเรามีสินค้าทั้งหมดกี่ชิ้นจะทำไง ?

👎 สิ่งที่ไม่ควรทำ: ไปดึงข้อมูลสินค้าทั้งหมดมาจากฐานข้อมูล แล้วให้ client เป็นคนนับเองว่ามีกี่ชิ้น ตามโค้ดด้านล่าง

ถ้าใครคิดแบบนี้ให้กลับไปอ่านตั้งแต่ต้นใหม่นะ เพราะมันโหลดข้อมูลทุกอย่างเลย ฐานข้อมูลต้องไปดึงข้อมูลยั้วเยี๊ย แล้วต้องไล่ส่งข้อมูลทั้งหมดผ่าน network อีก แล้วเอาข้อมูลปริมาณมากๆไปยัดให้ client ด้วย ขอแสดงความยินดีด้วย ที่ผมพิมพ์มาทั้งหมดไม่มีความหมายเลย T-T

👍 สิ่งที่ควรทำ: ตัวฐานข้อมูลมันเก่งเรื่องคณิตศาสตร์พื้นฐานอยู่แล้ว ดังนั้นก็ให้มันนับ records ทั้งหมดมาซิ แล้วส่งแค่ตัวเลขมาให้ client ก็พอ เพราะมันแทบจะไม่โหลดใครเลย

🤔 ถ้าอยากรู้ว่าสินค้าชิ้นนี้ถูกสั่งซื้อไปวันไหนบ้างจะทำไง ?

👎 สิ่งที่ไม่ควรทำ: ไปดึงข้อมูลคำสั่งซื้อทั้งหมดกลับมา แล้วค่อยหาคำสั่งซื้อของสินค้าชิ้นนั้น

รหัส P01 คือรหัสสินค้าที่เราต้องการหา

มันไม่ดีเพราะเหตุผลเดียวกันกับข้อที่แล้วเลย ซ้ำร้ายคือมันทำให้ client ต้องเสียเวลามานั่งประมวลผล filter ต่ออีกด้วย

👍 สิ่งที่ควรทำ: ให้ตัวฐานข้อมูลมันเก่งเรื่องคณิตศาสตร์พื้นฐานอยู่แล้ว ดังนั้นก็ให้มันนับ records ทั้งหมดมาซิ แล้วส่งแค่ตัวเลขมาก็พอ แทบจะไม่โหลดอะไรใครเลย

circle-check

🤔 ถ้าอยากรู้ข้อมูลลูกค้าทั้งหมดในระบบละ? สมมุติว่ามีเป็นล้านๆคนเลยนะ

👎 สิ่งที่ไม่ควรทำ: ไปดึงข้อมูลลูกค้าทั้งระบบมา -*- ไม่ขอเขียนตัวอย่างนะ

👍 สิ่งที่ควรทำ: ดึงข้อมูลมาเป็นส่วนๆ หรือที่เราเรียกว่า Paging นั่นเอง และในการดึงข้อมูลควรจะต้องดูด้วยว่าเราจะเอาข้อมูลอะไรของลูกค้าไปใช้บ้าง เช่น ถ้าในหน้านั้นมันเอาไปโชว์แค่ ชื่อ กับ นามสกุล เท่านั้น เราก็ไม่ต้องส่งข้อมูลจากฐานข้อมูลทั้ง record ก็ได้ โดยเราสามารถทำ Projection ได้นั่นเอง

circle-exclamation

🤔 แนวคิดนี้ใช้กับอะไรได้บ้าง ?

ใช้ได้กับฐานข้อมูลทุกแบบเลย มีฐานข้อมูลตัวไหนไม่ทำงานแบบนี้บ้าง? (อ่อจะบอกว่า embedded database ซินะ คิดเหรอว่ามันจะไม่มี network cost? และเรื่องอื่นๆที่ว่ามา)

triangle-exclamation

🎯 บทสรุป

จากที่ร่ายยาวมาก็จะเห็นแล้วว่า หัวใจ ในการทำงานกับฐานข้อมูลจริงๆก็มีแค่เรื่องนี้เรื่องเดียวแหละ เพราะต่อให้เราไปเตรียมทำ perfect design, indexing, cleansing, read/write replica บ้าบออะไรก็ตาม สุดท้าย ถ้าจุดเริ่มต้นมันกาก มันก็จะเหมือนกับแต่งรถไว้สุดเทพ มีเครื่องสุดแจ่ม มีน้ำมันสำรองครบ แต่ดันใส่เบรคมือทิ้งไว้แล้วขับลากเกียร์ 1 ตลอดทาง มันก็เท่านั้นแหละ จะไปนั่ง optimize มันทำไม?

ดังนั้นสุดท้ายก็หาทางปรับพื้นฐานในการทำงานกับ database ให้มันออกมาเป็นภาพนี้ให้ได้มากที่สุดเอาละกันนะจุ๊ฟๆ

Last updated

Was this helpful?