มีปัญหาเรื่อง 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 ชั่วโมง