Wordpress query caching in Memcached

มีปัญหาเรื่อง performance ของ wordpress อยู่เรื่องนึง ที่น่าหงุดหงิดใจมานานแล้ว คือในตอนที่ใช้ memcached มาทำเป็น cache backend ให้ wordpress เพื่อลดภาระของ database มันก็ช่วยได้เยอะอยู่ แต่ก็ยังมีบาง query ที่ตัว wordpress มันไม่ยอม cache ให้ ดังเช่น query ด้านล่างนี้

SELECT SQL_CALC_FOUND_ROWS  wp_posts.* FROM wp_posts  WHERE 1=1 
AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') 
ORDER BY wp_posts.ID ASC LIMIT 0, 1

เป็น query เจ้าปัญหาที่ถูกเรียกทุกครั้ง ทั้งๆ ที่ query อื่นถูก cache ไว้หมดแล้ว ทำให้ 1 request ที่เข้ามา ต้องมีการ query อย่างน้อย 1 query เสมอ ซึ่งดูเหมือนไม่เยอะเท่าไหร่ แต่ถ้าเว็บใหญ่ๆ ในระดับที่มีคนเข้าชั่วโมงละเป็นหลายหมื่น มันก็ทำให้ database ร่วงได้เหมือนกัน (อันนี้ยังไม่นับเรื่อง stampeding requests)

เมื่อมาลอง debug + ไล่โค้ดไปเรื่อยๆ ก็เจอเข้ากับ default filter ตัวหนึ่งของ wordpress ที่เพิ่มเข้ามาตอน wordpress 2.8 ที่ชื่อว่า start_post_rel_link มีหน้าที่แทรกแท็ก link เข้าไปที่ส่วน head ของหน้านั้นๆ ประมาณนี้

<link rel='start' title='Current Post Title'
href='http://www.pittaya.com/CurrentPostTitle/' />

แค่นี้แหละ ที่ต้องทำให้มี query ทุกๆ ครั้งที่เปิด (ซึ่งเป็น query ประเภท using filesort ที่ประสิทธิภาพห่วยอีกด้วย)

วิธีเอาออกก็ไม่ยากอะไร แค่ไป remove filter ออก โดยใส่โค้ดตามนี้ไว้ใน functions.php ของ theme ที่ใช้

remove_action('wp_head', 'start_post_rel_link', 10, 0);

แค่บรรทัดเดียวเท่านั้น ทำให้ลดโหลดของ database ลงไปได้มหาศาล สมกับคำโปรโมทของ wordpress ที่ว่า “โค้ดเป็นดั่งบทกวี”

เพียงแต่บทกวีบรรทัดนี้เสียเวลาเขียนอยู่ตั้ง 3 ชั่วโมง

Leave a Reply