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 ชั่วโมง

Checking wordpress user’s role

วิธีตรวจสอบว่า wordpress user ปัจจุบันว่าเป็น admin หรือไม่ ทีแรกมั่วๆ ไปดูที่ function is_admin() แต่อ่านโค้ดดูแล้วไม่ใช่ อันนั้นมันเอาไว้ดูว่าหน้าปัจจุบัน เป็นหน้า wordpress admin หรือเปล่า

วิธีตรวจสอบที่ถูก คือดูจาก capability ของ user นั้นๆ (reference สำหรับเช็ค capability ของ role ต่างๆ) โดยใช้ function current_user_can() เช็คว่าทำได้หรือไม่

เช่น จะดูว่า user สามารถลบคอมเมนต์ได้หรือไม่ ก็เช็คว่า current_user_can('moderate_comments') หรือถ้าต้องการจะเช็คจริงๆ ว่า user เป็น admin หรือเปล่า ก็ใช้ current_user_can('level_8')

แต่ถ้าสำหรับ wordpress MU จะมี function is_site_admin() ให้ใช้ด้วย

Change

ได้โอกาส เปลี่ยน theme ของบล็อกนี้เป็น plainscape theme หน้าตาก็ไม่ได้ต่างจากเดิมเท่าไหร่ เน้นเรียบๆ ไว้ก่อน จุดที่เอามาแก้ไขเพิ่มเติม (theme อันนี้เป็น GPL) ก็มีแก้ฟอนต์จาก Trebuchet MS มาเป็น Helvetica Neue แล้วก็ปรับสี / header เล็กน้อย

นอกจากนี้ก็ถือโอกาสเปลี่ยนสัญญาอนุญาต (License) ของเนื้อหาในบล็อกนี้เป็น ครีเอทีฟคอมมอนส์แบบ แสดงที่มา 3.0 ต้อนรับ Creative Commons ภาษาไทย ไปด้วยเลย