Database Performance

Query optimization, indexing, and measuring before optimizing.

Database Performance

Database Performance คือการบริหารจัดการทรัพยากรเพื่อให้ระบบสามารถดึงและบันทึกข้อมูลได้อย่างรวดเร็ว รองรับปริมาณการใช้งานที่เพิ่มขึ้น โดยไม่ส่งผลกระทบต่อ User experience

Cheat Sheet: Core Performance Concepts

ConceptDescription
Query Optimizationการปรับปรุงคำสั่ง SQL (หรือ ORM query) เพื่อให้ Database ทำงานน้อยที่สุดในการค้นหาผลลัพธ์ที่ต้องการ
Cachingการจัดเก็บผลลัพธ์ของ Query ที่ใช้บ่อยหรือข้อมูลที่เปลี่ยนแปลงน้อย ไว้ในระบบที่มีความเร็วสูง (เช่น In-memory database)
Connection Poolingการสร้างและจัดการกลุ่มของ Database connections ไว้ล่วงหน้า เพื่อลด Overhead ในการสร้าง Connection ใหม่ทุกครั้งที่มี Request

Practical Examples

1. Query Optimization with Indexing

Scenario: ตาราง users มีข้อมูล 10 ล้านเรคคอร์ด การค้นหาผู้ใช้ด้วยอีเมลใช้เวลามากกว่า 3 วินาที Practice: การใช้คำสั่ง EXPLAIN หรือ EXPLAIN ANALYZE จะพบว่า Database กำลังทำ Sequential Scan (สแกนทุกแถว) Solution: สร้าง Index บนคอลัมน์ email

CREATE INDEX idx_users_email ON users(email);

หลังจากสร้าง Index Database จะสามารถค้นหาข้อมูลผ่าน B-Tree structure ลดเวลาการค้นหาจากระดับวินาทีเหลือเพียงเสี้ยวของมิลลิวินาที (Index Scan)

2. Caching Expensive Queries

Scenario: Dashboard ของระบบต้องแสดงผลสรุปยอดขายรายวัน ซึ่งเป็น Query ที่มีการคำนวณซับซ้อน (Aggregations) และใช้เวลาทำงาน 5 วินาที Practice: แทนที่จะให้ Database คำนวณใหม่ทุกครั้งที่มีผู้ใช้เปิด Dashboard เราสามารถนำ Redis มาประยุกต์ใช้เพื่อทำ Caching Workflow:

  1. Application ตรวจสอบว่ามีข้อมูลยอดขายใน Redis หรือไม่
  2. หากมี (Cache Hit): ส่งข้อมูลให้ผู้ใช้ทันที
  3. หากไม่มี (Cache Miss): ส่ง Query ไปยัง Database, นำผลลัพธ์ที่ได้ไปจัดเก็บใน Redis (กำหนด Time-To-Live หรือ TTL เช่น 10 นาที), และส่งข้อมูลให้ผู้ใช้ Result: ระบบสามารถรองรับผู้ใช้งานพร้อมกันได้จำนวนมากโดยไม่สร้างโหลดให้ Database

3. Connection Pooling for High Concurrency

Scenario: แอปพลิเคชันมี Traffic สูงขึ้นอย่างฉับพลัน (Spike) ทำให้ระบบแสดงข้อความ Error "Too many connections" Practice: Database ส่วนใหญ่มีข้อจำกัดในการรองรับ Concurrent connections การสร้าง Connection ใหม่มี Overhead สูงในระดับ Network และ Authentication Solution: นำ Connection Pooler (เช่น PgBouncer สำหรับ PostgreSQL) มาคั่นกลางระหว่าง Application และ Database

  • Application จะทำการเชื่อมต่อไปยัง Connection Pool
  • Connection Pool จะบริหารจัดการและหมุนเวียน (Reuse) Connection จริงที่มีต่อ Database
  • เมื่อมีการส่ง Request จำนวนมากเกินกว่าที่ตั้งไว้ Request เหล่านั้นจะถูกจัดคิวรอ (Queue) แทนที่จะทำให้ Database ทำงานหนักจนล่ม

4. Avoiding N+1 Query Problem

Scenario: การแสดงรายการบทความพร้อมชื่อผู้เขียนผ่าน ORM Practice: การดึงข้อมูลผิดวิธีอาจทำให้เกิดคำสั่ง SQL จำนวนมาก Bad Practice (N+1):

const posts = await Post.find(); // 1 Query
for (let post of posts) {
  const author = await User.findById(post.authorId); // N Queries
}

Good Practice (Eager Loading / Joins):

const posts = await Post.find().populate('author'); // 1 Optimized Query

การปรับ Query Shape ด้วย Join หรือ Eager loading ช่วยลดระยะเวลาที่ระบบต้องติดต่อกับ Database ได้อย่างมีนัยสำคัญ

AI Knowledge Assistant

สวัสดีครับ! ผมคือ AI Assistant ประจำเว็บไซต์

คุณสามารถสอบถามข้อมูลด้าน Computer Science, Business, หรือ Finance ได้เลยครับ