วิธีทำ Website / MySQL ให้โหลดโคตรเร็วและรองรับคนปริมาณมาก ๆ

วิธีทำ-Website-MySQL-ให้โหลดโคตรเร็ว-2
วิธีทำ-Website-MySQL-ให้โหลดโคตรเร็ว-2

วิธีทำ Website / MySQL ให้โหลดโคตรเร็วและรองรับคนปริมาณมาก ๆ



วิธีทำ Website / MySQL ให้โหลดโคตรเร็วและรองรับคนปริมาณมาก ๆ

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

คำถามคือการเข้าชมแบบพร้อม ๆ กันหลักหมื่นคน จะเกิดขึ้นได้ยังไง จากที่เคยเจอคือ เกิดจากการปล่อย push notification และ จากการแชร์ลงไปใน pages หรือ group facebook ที่มีสมาชิกจำนวนมาก ๆ เพราะฉะนั้น กรณีเกิดขึ้นได้แน่นอนครับ

แนวทางการทำให้ website และ database รองรับคนปริมาณมาก ๆ

ทุกข้อตามด้านล่าง ถ้าทำแล้วจะเห็นผลชัดเจนทุกข้อ โดยเฉพาะ ข้อ 4 และข้อ 5 จะทำให้การโหลดหน้าเพจเร็วขึ้นหลายสิบเท่าตัวครับ สามารถทดสอบได้โดยการติดตั้ง chrome extension page load time และดูเวลาที่ใช้ในการโหลดได้ครับ ถ้าทำครบทั้ง 5 ข้อ สามารถให้หน้าเว็บหนัก ๆ โหลดเร็วแบบไม่ถึงวินาทีได้เลย

  • 1. กำหนด max_connection ให้เพียงพอกับการเข้าชมพร้อม ๆ กัน
  • โดยปกติค่าเริ่มต้นของ Hosting ทั่วไปจะกำหนดจำนวนการเชื่อมต่อฐานข้อมูลไว้ประมาณ 200 – 300 concurrent connection หมายความว่า ถ้ามีคนเข้าเว็บไซต์เราพร้อม ๆ กัน 300 คน Database Error ทันทีครับ แต่ปกติแล้ว ถ้าเว็บไซต์ที่ไม่ได้มี traffic มากมายอะไร โอกาสที่จะเกิดขึ้นน้อยมาก เพราะโดยส่วนใหญ่แล้ว การเชื่อมต่อจะเป็นในลักษณะ เชื่อมต่อ โหลดข้อมูลเสร็จ แล้วก็ปิดการเชื่อมต่อ ทำให้มี connection ว่างสำหรับคนเข้าชมต่อ ๆ ไป แต่ถ้าโจทย์ของเราคือการ รองรับการเข้าชมพร้อม ๆ กัน 1 หมื่นคน ให้กำหนด max_connection เกินหมื่นคนขึ้นไปครับ
    สามารถดูตัวเลข max_connection ได้ที่ phpMyAdmin/Variables/max_connection หรือใช้คำสั่งคิวรี่ด้านล่างครับ

    show variables like "max_connections";


  • 2. Query ให้น้อยที่สุดและ Query มาใช้เฉพาะที่ต้องใช้
  • ลดการ select ข้อมูลใน 1 หน้าให้น้อยที่สุดเท่าที่จะทำได้ select ข้อมูลเท่าที่จำเป็นเท่านั้น หลีกเลี่ยงการใช้ select * เพื่อลดปริมาณการ query การนับจำนวน record ให้ใช้การเพิ่ม field แทนการใช้ select และ count(array) ตัวอย่างเช่น ถ้าเราต้องการแสดงตัวเลขจำนวนสินค้าในหมวดหมู่ไอที แทนที่จะใช้วิธีนี้

    $result = $this->db->query("select * from product where product_type = 1");
    $maxItproduct = count($result);

    ให้เปลี่ยนเป็นการเพิ่ม field max_item ใน table product_type แทน เพื่อลดการ query การ loop หาจำนวนสินค้าในหมวดหมู่นั้น ๆ

  • 3. ใช้ loop ในหนึ่งหน้าให้น้อยที่สุด
  • แน่นอนครับว่าการใช้ loop นั้นมีผลโดยตรงกับการประมวลผลโดยรวมของหน้าเว็บไซต์ ยิ่งปริมาณไอเทมที่ loop มากเท่าไหร่ และภายใน loop นั้นมีการคำนวณ การประมวลผลที่ซับซ้อนมากเท่าไหร่ จะยิ่งทำให้การโหลดหน้าเว็บไซต์ใช้เวลามากขึ้นเท่านั้น ให้หลีกเลี่ยงการใช้ loop ซ้อนอยู่ภายใน loop การ query ข้อมูลภายใน loop วิธีการหลีกเลี่ยงที่ดีที่สุด ก็คือการออกแบบฐานข้อมูลให้พร้อมนำมาใช้งานมากที่สุด

  • 4. ต้องทำ Database Caching
  • การทำ db caching นั้นจะลดการประมวลผลของหน้าเว็บไซต์และทำให้การโหลดหน้าเว็บไซต์เร็วขึ้นมาก มากแบบหลายเท่าตัว จากปกติเว็บไซต์เราอาจจะใช้เวลาโหลด 5.20 วินาที การทำ db caching อาจจะทำให้หน้าเว็บใช้เวลาโหลดลดลงเหลือเพียง 0.20 วินาทีเท่านั้น
    เว็บไซต์แบบ dynamic content หมายถึงเว็บไซต์ที่มีการปรับปรุงเปลี่ยนแปลงข้อมูลบนหน้าเว็บไซต์เป็นประจำ กล่าวคือการดึงข้อมูลจาก database มาแสดงผลบนหน้าเว็บไซต์ การทำ db caching คือการดึงข้อมูลมาแสดงเพียงครั้งแรกครั้งเดียว และครั้งต่อ ๆ ไปเป็นการใช้ cache ข้อมูล จนกว่าจะครบกำหนดเวลาค่อยไปถึงข้อมูลมา update เป็น cache อีกครั้ง ซึ่งการกำหนดช่วงเวลาของการอัพเดทก็จะขึ้นอยู่กับว่าข้อมูลนั้นมีความจำเป็นจะต้องอัพเดทบ่อยขนาดไหน อาจจะอัพเดททุก 30 นาที 1 วัน หรือ 1 เดือนเป็นต้น ตัวอย่างการทำ cache db ใน codeigniter

    // เปิดการเก็บ cache สำหรับเทเบิ้ล product เพราะสินค้ามีปริมาณมาก
    $this->db->cache_on();
    $query = $this->db->query("SELECT * FROM product");
    
    // ไม่เก็บ cache สำหรับสมาชิกที่กำลังออนไลน์อยู่ เพราะมีข้อมูลบางส่วนที่ต้องอัพเดทแบบ real time
    $this->db->cache_off();
    $query = $this->db->query("SELECT * FROM members WHERE member_id = '$current_user'");
    
    // เปิดการเก็บ cache สำหรับเทเบิ้ล category เพราะไม่มีการอัพเดทบ่อย ๆ อยู่แล้ว
    $this->db->cache_on();
    $query = $this->db->query("SELECT * FROM category");


  • 5. ใช้ MyISAM และกำหนด Indexes
  • ฐานข้อมูลประเภท MyISAM มีจุดเด่นในเรื่องของความเร็วในการอ่านและการเขียนอยู่แล้ว ซึ่งเร็วกว่า InnoDB แน่นอนครับและยิ่งถ้าเราทำ indexes ให้กับทุก ๆ field ที่ต้อง where หาอยู่บ่อย จะยิ่งเพิ่มความเร็วในการ query มากหลายเท่าตัวครับ ยกตัวอย่างเช่น ในเทเบิ้ล category เราต้อง select และ where หา cate_id อยู่บ่อย ๆ ทำไมไม่กำหนด indexes ให้ cate_id ไปเลย จะได้หาง่ายขึ้น การทำ indexes ไม่ได้ทำที่ตอน query นะครับ ให้เข้าไปทำใน phpMyadmin เลย เลือกที่ more และ index

    วิธีทำ-Website-MySQL-ให้โหลดโคตรเร็ว-1.png


    หรือใช้คำสั่ง SQL

    ALTER TABLE `apps_member` ADD INDEX(`member_id`);



ถ้าทำครบทั้ง 5 ข้อด้านบน เว็บไซต์จะโหลดเร็วขึ้นทันตาเห็นแน่นอนครับ หวังว่าจะเป็นประโยชน์