คำตอบสั้น ๆ: คำนวณขนาด innodb_buffer_pool_size ให้เหมาะกับ RAM และขนาดข้อมูล วัดอัตรา Cache Hit แล้วปรับค่าทั้งแบบออนไลน์และถาวร เพื่อให้ฐานข้อมูลตอบสนองเร็วขึ้น
คู่มือนี้อธิบาย innodb ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
MySQL และ MariaDB ที่ติดตั้งจากแพ็กเกจมาตรฐานตั้งค่าหน่วยความจำไว้ต่ำมาก innodb_buffer_pool_size ซึ่งเป็นพื้นที่ใน RAM สำหรับเก็บข้อมูลและ Index ของตาราง InnoDB มีค่าเริ่มต้นเพียง 128 MB ถ้าฐานข้อมูลของคุณใหญ่กว่านั้น ทุก Query จะต้องอ่านจากดิสก์ซ้ำแล้วซ้ำอีก ทำให้เว็บช้าทั้งที่ RAM ของเซิร์ฟเวอร์ยังว่างอยู่มาก
บทความนี้อธิบายวิธีคำนวณขนาด Buffer Pool ที่เหมาะกับเครื่อง ตรวจว่าค่าปัจจุบันพอหรือไม่ ปรับค่าทั้งแบบออนไลน์และแบบถาวร และค่าที่เกี่ยวข้องอีกเล็กน้อยที่ควรดูพร้อมกัน เป็นการปรับแต่งเบื้องต้นที่ได้ผลมากที่สุดสำหรับเว็บไซต์ทั่วไป เช่น WordPress หรือร้านค้าออนไลน์
สิ่งที่ต้องเตรียม
- MySQL 8.0/8.4 หรือ MariaDB 10.x/11.x บน Linux และสิทธิ์ root
- ทราบขนาด RAM ของเครื่องและบริการอื่นที่รันอยู่ด้วย (Web Server, PHP-FPM, Redis ฯลฯ)
- ตารางส่วนใหญ่ใช้ Engine InnoDB (ค่าเริ่มต้นของทั้ง MySQL และ MariaDB รุ่นปัจจุบัน)
ขั้นตอนที่ 1: ดูข้อมูลพื้นฐานของเครื่อง
free -h
nproc
total used free shared buff/cache available
Mem: 7.7Gi 2.1Gi 1.2Gi 60Mi 4.4Gi 5.3Gi
Swap: 2.0Gi 0B 2.0Gi
ดูคอลัมน์ total และ available ถ้าเครื่องใช้ Swap อยู่มากแล้ว ต้องแก้เรื่อง RAM ไม่พอก่อน การเพิ่ม Buffer Pool จะยิ่งทำให้แย่ลง ดู ตรวจสอบ CPU, RAM และ Load Average ของ Linux Server
ขั้นตอนที่ 2: ดูขนาดข้อมูล InnoDB และค่าปัจจุบัน
sudo mysql
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024) AS innodb_mb
FROM information_schema.tables
WHERE engine = 'InnoDB';
SELECT @@innodb_buffer_pool_size / 1024 / 1024 AS buffer_pool_mb;
ตัวอย่างผลลัพธ์ข้อมูล 1,450 MB แต่ Buffer Pool มีเพียง 128 MB แปลว่ามีข้อมูลน้อยกว่า 10% เท่านั้นที่อยู่ใน RAM ได้ Buffer Pool ในอุดมคติควรใหญ่กว่าขนาดข้อมูลที่ใช้งานบ่อยเล็กน้อย ไม่จำเป็นต้องใหญ่กว่าข้อมูลทั้งหมด
ขั้นตอนที่ 3: วัดอัตรา Cache Hit
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
Innodb_buffer_pool_read_requests 98231455
Innodb_buffer_pool_reads 1203344
read_requests คือจำนวนครั้งที่ขออ่านข้อมูล ส่วน reads คือจำนวนครั้งที่ไม่พบใน RAM และต้องไปอ่านจากดิสก์ คำนวณอัตราพลาดได้ดังนี้
SELECT ROUND(100 * r.v / q.v, 2) AS miss_percent
FROM (SELECT VARIABLE_VALUE AS v FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads') r,
(SELECT VARIABLE_VALUE AS v FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') q;
บน MariaDB ให้เปลี่ยน performance_schema.global_status เป็น information_schema.GLOBAL_STATUS (หรือคำนวณด้วยมือจากตัวเลขข้างบน) ตัวอย่างนี้ได้ประมาณ 1.2% ถ้าเกิน 1% อย่างต่อเนื่องหลังเครื่องทำงานมาหลายชั่วโมง แปลว่า Buffer Pool เล็กเกินไป ค่านี้นับสะสมตั้งแต่เริ่มบริการ จึงควรวัดหลังจากฐานข้อมูลทำงานมาระยะหนึ่ง ไม่ใช่ทันทีหลังรีสตาร์ต
ขั้นตอนที่ 4: คำนวณขนาดที่เหมาะสม
หลักคิดคือให้ Buffer Pool ใหญ่ที่สุดเท่าที่ทำได้ โดยยังเหลือ RAM ให้ระบบปฏิบัติการ บริการอื่น และหน่วยความจำต่อการเชื่อมต่อของฐานข้อมูลเอง
| ลักษณะเครื่อง | สัดส่วนที่แนะนำ | RAM 4 GB | RAM 8 GB | RAM 16 GB |
|---|---|---|---|---|
| เครื่องฐานข้อมูลโดยเฉพาะ | 60-70% ของ RAM | 2.5 GB | 5 GB | 11 GB |
| รวมกับ Web Server และ PHP (เช่น WordPress) | 25-40% ของ RAM | 1 GB | 2-3 GB | 5 GB |
| มี Control Panel เช่น Plesk ร่วมด้วย | 20-30% ของ RAM | 768 MB-1 GB | 2 GB | 4 GB |
ไม่ต้องตั้งให้ใหญ่กว่าขนาดข้อมูล InnoDB ในขั้นตอนที่ 2 มากนัก ถ้าข้อมูลทั้งหมดมี 1.5 GB การตั้ง 6 GB ไม่ได้ช่วยอะไร ตั้งราว 2 GB ก็พอและมีที่ให้ข้อมูลโตได้ ตัวเลขในตารางเป็นจุดเริ่มต้น ควรดูผลจริงหลังปรับเสมอ
หมายเหตุ: ถ้าตั้งค่าสูงเกินไปจนระบบไม่มี RAM เหลือ Linux จะเรียก OOM Killer มาหยุดโปรเซสที่ใช้หน่วยความจำมากที่สุด ซึ่งมักเป็นฐานข้อมูลเอง ทำให้เว็บล่มกะทันหัน ปรับขึ้นทีละขั้นดีกว่าตั้งสูงครั้งเดียว