0010 | MySQL Memory Engine

Saturday, May 10th, 2008 Posted in Database | 2 Comments »

ก่อนอื่นขอรายงานสถานการณ์+บ่นซะก่อน แง่มๆ
วันที่ 7 ตอน 22.00 น. ไฟฟ้าใช้ได้ตามปกติแล้วครับ
แล้วก็… aircard กลับมาใช้ได้ตามปกติแล้ว เย้ๆๆ
เซ็งแทบตาย ต้องไปจิ้มสายเน็ตเพื่อนใช้อยู่ แล้วมันเร็ว
เอ้ย แล้วมันต้องเกรงใจอะ น่าเบื่อที่สุด ทำอะไรไม่สะใจเลย

กลับเข้าเรื่องกันดีกว่า
วันนี้จะมาว่าด้วย MySQL Memory Engine ครับ

Memory Engine เป็นรูปแบบตารางของ MySQL แบบหนึ่ง
ซึ่งมีโครงสร้างคล้ายๆ กับ MyISAM บ้าง นิดๆ หน่อยๆ
เพียงแต่แทนที่จะเก็บไว้เป็นไฟล์ .MYD ไว้บนเครื่อง ก็เปลี่ยนมาเป็น
เก็บลง shared memory ของ master process แทน
แน่นอนครับ ผลลัพท์ที่ได้มันก็มาจากความเร็วของ RAM ที่ท่านใช้
ว่ามันจะเร็วได้แค่ไหน ซึ่งปกติ ประสิทธิภาพความเร็วที่ทำได้จะอยู่ราวๆ 0000ff;">50-150 เท่าของ MyISAM ครับ

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

  1. เครื่องมีแรมเท่าไหร่ มันก็เก็บได้ไม่เกิน 1/2 ของแรมนั่นแหละครับ
  2. ใช้ field ประเภท text/blob ทุกชนิดไม่ได้ (ใช้ varchar ได้อยู่นะครับ)
  3. restart mysql ปุ๊ป ข้อมูลหายเรียบ (ก็มันเก็บในแรมนี่)
  4. เปลืองพื้นที่มากกว่า MyISAM เยอะ (ตาราง MyISAM ขนาด 10 MB เวลาแปลงเป็น Memory จะใช้แรมประมาณ 40 MB)
  5. ต้อง allocate memory เป็น block แต่ละ block ขนาดประมาณ 4-8 MB (เอาเป็นว่าหารเลขฐานสองลงตัวอะ)

ว่าแต่ร่ายซะเสียเลยแฮะเรา (ฮาๆ)
เอาเป็นว่า เนื่องด้วยเหตุผลข้อ 3 ทำให้เราไม่สามารถเก็บข้อมูลลงใน Memory Engine ได้ถาวรแน่นอนครับ
ดังนั้น ตารางแบบนี้เหมาะสำหรับเก็บค่า “ชั่วคราว” มากกว่า
เช่นพวกสถิติ user online, session ของเว็บไซต์ อะไรพวกนี้
ซึ่งวิธีแปลงก็ง่ายๆ ครับ

ALTER TABLE 0000ff;">table ENGINE=Memory;

แค่นี้เอง สั้นๆ ง่ายๆ ได้ใจความ
รูปแบบการใช้งานที่เหมาะสม (และผมใช้อยู่ปัจจุบัน)คือ ตาราง peers ของเว็บ bittorrent ครับ
reset ไปมันก็เข้าใหม่ได้ ไม่มีปัญหาอะไรมาก แถมตารางนี้ access หนักมาก ถี่ยิบๆ
ก็เลยเหมาะต่อการใช้ Memory Engine ที่สุดเลย

รองลงมาก็คือ download session ของเว็บฝากไฟล์
พวกนี้ปล่อยๆ มันได้ครับ ใช้ไม่่ค่อยเยอะหรอก

ทีนี้ ปัญหาที่จะเจอคือ Error ต่อไปนี้

The table ‘ff0000;">table‘ is full

ทั้งนี้เนื่องมาจาก MySQL มีการกำหนดขนาดสูงสุดของตารางประเภท Memory ไว้ครับ
ว่า 1 ตารางสามารถจุข้อมูลได้ทั้งหมดกี่ MB ใน variable ที่ชื่อ 0000ff;">max_heap_table_size ครับ
โดยค่าปกติของ MySQL 5.0 คือ 16 MB
อยากให้มันใหญ่ได้เท่าไหร่ก็ใส่ไปโลด /etc/my.cnf ในส่วนของ mysqld สั้นๆ ง่ายๆ ครับ

จบและ คราวหน้าถ้าไม่ลืมจะมาพูดถึง MySQL Indexes ครับ

Tags: , ,

0004 | PHP Memory Limit

Saturday, May 3rd, 2008 Posted in PHP Coding | No Comments »

Fatal error: Allowed memory size of 262144 bytes exhausted (tried to allocate 4864 bytes) in /path/to/script.php on line 1074

ข้อผิดพลาดนี้ (อันที่จริงก็ทุกอัน) คนทำเว็บคนไหนก็คงไม่ชอบให้มันขึ้นมาหรอกจริงมั้ยครับ
วันนี้จะมาอธิบายการทำงานของ memory limit นิดนึง…

การที่ error อันนี้ขึ้นมาเนี่ย มันกำลังพยายามบอกว่า
ก่อนหน้านี้ มีการขอใช้หน่วยความจำไปแล้วจนเกือบเต็ม 262144 byte (คือเหลือหน่วยความจำว่างๆ อีกไม่เยอะ)
แล้วมีการขอใช้เพิ่มอีก 4864 byte แต่พื้นที่หน่วยความจำที่เหลืออยู่ (ตามที่อนุญาตไว้) มีไม่พอให้ใช้
มันก็เลยต้องจบการทำงานลง เพราะหน่วยความจำหมด

นี่แหละครับคือหน้าที่ของ memory limit

ตัว memory limit มีไว้สำหรับจำกัดการใช้งานหน่วยความจำ ของ “ตัวแปร” ใน PHP ครับ
แบ่งเป็นตัวแปรจากระบบ (พวก $_SERVER $_GET $_POST $_ENV $_SESSION $_COOKIE)
พวกนี้กินอย่างมากก็ประมาณ 50 KB ครับ แล้วที่เหลือก็เป็นส่วนของการทำงานใน code ไป

เชื่อมั้ยครับว่าค่าที่เหมาะสมสำหรับเว็บทั่วไปอยู่ที่ “2M” เอง เพราะปกติเราก็ไม่ใช้อะไรเยอะแยะอยู่แล้ว
สำหรับเว็บที่มีการเรียกใช้ gd library (พวกที่มี captcha อะไรพวกนี้ด้วย) ควรปรับประมาณ 16-24 M
แล้วก็ เว็บฝากไฟล์…. ใช้เท่ากะเว็บปกติครับ (สำหรับส่วนของการ upload)
เนื่องจาก content ในไฟล์ ไม่ได้ถูกนำมาเก็บในหน่วยความจำครับ
ส่วนพวก CMS ต่างๆ เช่น joomla / mambo / phpnuke / wordpress / drupal พวกนี้ควรตั้งขั้นต่ำที่ 8M ครับ
แล้วก็พวก webboard เช่น SMF / IPB / vBullentin / phpBB ควรตั้งขั้นต่ำ 16M ครับ

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

$test = “”;
while (1) {
$test .= “more”;
}

ถ้าเกิดไม่มี memory limit นี่เครื่องพังแน่นอนครับ (ใช้แรมเกิน)
แต่กรณีปกติที่อาจจะเกิด คือเขียน script วนซ้ำ แล้วเงื่อนไขการวนซ้ำผิดพลาด
ทำให้เกิดการวนซ้ำไม่รู้จบ (infinite loop) จนมีการจองหน่วยความจำเพิ่มขึ้นเรื่อยๆ
แล้วสุดท้าย หน่วยความจำล้น (buffer overflow) เป็นเหตุให้โดน hack หรืออะไรต่างๆ ตามมาได้มากครับ

วิธีการตรวจสอบหน่วยความจำที่ใช้ไปแล้ว
ใน PHP จะมี function ตัวนึงครับ ไว้เรียกใช้เพื่อดูว่า
ตั้งแต่บรรทัดแรก จนถึง code บรรทัดที่เรียกคำสั่งนี้ ใช้ memory ไปแล้วเท่าไหร่

http://th.php.net/manual/en/function.memory-get-usage.php

ดูใน docs นะครับ ใช้ไม่ยากๆ

ปล. entry นี้อ้างอิงจากที่ > ThaiSEOBoard # ความงี่เง่าของ SLHost <

ปปล. entry นี้เขียน ปล. ก่อนเนื้อหาซะอีก

Tags: , ,