เพิ่ม Index ให้ WordPress เพื่อลดโหลด

อันนี้เป็นบทความสั้นๆครับ เกิดจากการสังเกตว่าใน WordPress ของผมนั้นจะมี Query อันนึงที่ run เยอะมาก และบางทีก็นานมาก ตัวอย่างประมาณนี้ครับ

SELECT post_id FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2015/11/top-5-antivirus.jpg';

ซึ่งจากที่เดาคือมันเช็คว่า Attachment ตัวนี้มี Post ไหนใช้บ้าง ผมไม่รู้ว่าตัวไหนเป็นคนเรียกใช้ แต่เนื่องจากมันเยอะมาก เลยทำการเพิ่ม index ให้มัน ทำให้มัน Query ได้เร็วขึ้น

ALTER TABLE wp_postmeta ADD INDEX first_50_key_10_value (meta_key(50),meta_value(10))

เพื่อความประหยัดผมเลย index meta_value แค่ 10 ตัวพอ (เพียงพอสำหรับ /ปี/เดือน/ ก็ลดไปได้เยอะและ)

แต่อันนี้ไม่ได้ช่วยกับทุกคนนะครับ บางทีมันอาจจะมาจาก Theme หรือ Plugin ก็ได้ ดังนั้นต่อให้ท่านใช้ไปก็ไม่อาจจะรับประกันได้ว่ามันจะช่วยท่านได้

วิธีทำให้เข้าสู่ระบบ WordPress ใน Domain และ SubDomain ในครั้งเดียว

เกริ่นปัญหา

ปัญหาของเรื่องนี้มาจากโพสนี้ครับ สรุปคือเค้าอยากได้ WordPress 2 ตัวที่ใช้ฐานข้อมูลผู้ใช้อันเดียวกัน และเข้าสู่ระบบที่นึง อีกที่จะเข้าสู่ระบบด้วย โดยหลังจากผมลองค้นหาดู พบว่าสามารถทำได้ แต่ทำได้ในระดับแค่ Sub Domain หรือ Sub Directory เท่านั้นนะครับ และ Database ต้องใช้ Database เดียวกัน (ผมเข้าใจว่าสามารถทำได้ถึงระดับที่อยู่คนละ Database แต่ต้องเป็นที่เดียวกันและใช้ Username/Password เหมือนกัน)

วิธีทำ

  1. ก่อนอื่นให้ลง WordPress ทั้ง 2 ที่แบบปกติให้เรียบร้อยก่อน (ถ้ามีแล้ว ข้ามไปครับ)
  2. ลง Plugins “WP-Orphanage Extended” ให้ WordPress ทั้ง 2 ตัว แล้วไปตั้งค่าใส่ prefix ให้เรียบร้อยครับ
  3. ทำการแก้ไข wp-config.php ของ WordPress ทุกตัวดังนี้ครับ
    <?php
    // แทน xxx ด้วยค่าเดิมนะครับ แต่ทุกไฟล์ที่เป็น wp-config.php ต้องเหมือนกันหมด
    define('AUTH_KEY', 'xxx');
    define('SECURE_AUTH_KEY', 'xxx');
    define('LOGGED_IN_KEY', 'xxx');
    define('NONCE_KEY', 'xxx');
    define('AUTH_SALT', 'xxx');
    define('SECURE_AUTH_SALT', 'xxx');
    define('LOGGED_IN_SALT', 'xxx');
    define('NONCE_SALT', 'xxx');
    
    // ตั้งค่า Cookie ให้ Login แล้วใช้ได้ทุก sub domain 
    // อย่าลิมแก้ .example.com เป็น domain ตัวเอง (ไม่ต้อง www)
    // อย่าลืมจุดหน้า domain มันสำคัญมาก ผมไม่ได้พิมพ์ผิด 
    define('COOKIE_DOMAIN', '.example.com'); 
    define('COOKIEPATH', '/');
    define('SITECOOKIEPATH', '/');
    define('PLUGINS_COOKIE_PATH', '/');
    define('ADMIN_COOKIE_PATH', '/');
    
    // ตั้งชื่อ Cookie ที่ใช้เวลา Login 
    define('AUTH_COOKIE','wordpress_auth_cookie');
    define('SECURE_AUTH_COOKIE','wordpress_auth_cookie');
    
    // บอกว่าจะใช้ User จากตารางไหน 
    define('CUSTOM_USER_TABLE','wp1_users');
    define('CUSTOM_USER_META_TABLE','wp1_usermeta');
  4. ทดสอบได้เลยครับ

ความเห็นส่วนตัว

จริงๆคิดว่าถ้าจะทำแบบนี้น่าจะทำเว็บเดียวแล้วแยก Category ของบทความน่าจะดีกว่า แล้วปรับ Theme เอา โดยใช้ Template Hierarchy หรือ Condition Tags ช่วยก็จะได้ 2 ส่วนที่หน้าตาไม่เหมือนกัน แต่ข้อมูลเหมือนกันแล้ว (ช่วยได้ระดับนึงนะ) หรือไม่ก็แยก Post Type ไเลยก็ได้ครับ

วิธีทำให้ WordPress ใช้ AMP ได้ + วิธีใส่โฆษณาในหน้า AMP

AMP คืออะไร

AMP หรือชื่อเต็มคือ Accelerated Mobile Pages เป็นมาตรฐานหน้าเว็บความเร็วสูงชนิดหนึ่ง ที่ประกาศใช้โดย Google เพื่อให้สามารถแสดงผลหน้าเว็บบนมือถือได้เร็วที่สุด โดยจะมีแท็กใหม่ๆที่ถูกประกาศออกมาโดย Google เอง และ HTML5 ปกติ เพื่อให้ได้ความเร็วสูงสุดในการเข้าถึงหน้าเว็บ โดยมีข้อกำหนดบางอย่างเพื่อให้หน้าเว็บเร็วขึ้น เช่น

  • การใช้รูปต้องมีการประกาศจองที่ว่ากว้างสูงเท่าไหร่ เพื่อให้ Browser จองที่ไว้ จะได้ไม่ต้องมีการ reflow บ่อยๆ
  • มีการบังคับว่าแท็ก script ทุกตัวต้องเป็น async เพื่อให้ผู้ใช้เห็นหน้าเว็บได้เลย ไม่ต้องรอโหลด script ก่อน
  • นอกจากนั้นหน้าเว็บ AMP จะจัดลำดับความสำคัญของการโหลดด้วยตัว AMP เอง เช่นบังคับให้โฆษณาโหลดหลังเนื้อหาเป็นต้น

เราจะใช้ AMP ได้อย่างไร

วิธีใช้ง่ายๆ

  1. ก่อนอื่นเข้าไปดูข้อกำหนดต่างๆ ในเว็บของ AMP  จากนั้นให้สร้างหน้าใหม่สำหรับเนื้อหาแต่ละหน้า โดยใช้ข้อกำหนดต่างๆในเว็บ AMP (มันมีเยอะ ผมไม่ขอพูดถึงนะครับ)
  2. หลังจากเราได้หน้าใหม่มาแล้ว ในหน้าเนื้อหาเก่า เพิ่ม code ส่วนนี้ลงใน head
    <link rel="amphtml" href="http://example.com/amp.html" />

    อย่าลืมแก้ URL เป็นหน้า AMP ที่สร้างสำหรับหน้านั้น เป็นอันเสร็จสิ้นครับ

วิธีใช้ AMP สำหรับ WordPress

จากวิธีด้านบน ยุ่งยากใช้ไหมครับ คำตอบใช่ครับ สำหรับท่านที่ใช้ WordPress เรามีวิธีที่ดีกว่ามานำเสนอ นั้นคือติกตั้ง Plugin AMP ซึ่งสามารถดาวโหลด Plugin AMP ได้โดยคลิกลิงครับ เสร็จแล้วก็ติดตั้งลง WordPress ให้เรียบร้อย ถ้ามี Cache ก็ clear cache ซำ เท่านี้ก็สามารถใช้งาน AMP ได้แล้วครับ สามารถทดสอบได้โดย สมมุติ URL เราเป็น

https://www.ishare.in.th/articles/วิธีทำให้-wordpress-ใช้-amp-ได้-วิธีใส่โฆษณาในหน้า-amp

เราก็เติม /amp ลงไปด้านหลัง มันจะแสดงหน้าเว็บฉบับ AMP ให้ (ใช้ได้บน Chrome เท่านั้นนะครับ ตัวอื่นอาจจะแสดงผลไม่สมบูรณ์ เช่นโฆษณาไม่แสดงเป็นต้น) จะได้เป็น

https://www.ishare.in.th/articles/วิธีทำให้-wordpress-ใช้-amp-ได้-วิธีใส่โฆษณาในหน้า-amp/amp

ต้องบอกว่า plugin ตัวนี้ จะแสดงหน้า AMP ที่มีแค่เนื้อหาโพสเท่านั้นนะครับ ไม่มีความเห็น หรือส่วนอื่นๆ เพราะมันไม่ตรงข้อกำหนดของ AMP

ถ้าต้องการใส่โฆษณาให้หน้า AMP ทำยังไง

สำหรับใครที่ใช้ WordPress สามารถทำตามนี้ได้เลยครับ (แนะนำควรมีความรู้ php html ละดับนึงนะครับ เพื่อเกิดปัญหาจะได้แก้ปัญหาเฉพาะหน้าได้ หรืออย่างน้อยๆควร backup ไว้ก่อนครับ) สำหรับใครที่ไม่ได้ใช้ WordPress ก็น่าจะสามารถเดาจากด้านล่างได้เลยครับ ไม่น่ายาก

  1. ให้แก้ไข functions.php ในโฟลเดอร์ theme ของเรา
  2. ให้เพิ่มโคดไปดังนี้ครับ ดังตัวอย่างอันนี้เป็นของ Google Adsense
    <?php
    function show_amp_ads(){
    ?>
    <div style="text-align:center">
    <amp-ad width=320 height=100
    type="adsense"
    data-ad-client="ca-pub-2132417031705165"
    data-ad-slot="6260362044">
    </amp-ad>
    </div>
    <?php
    }
    add_action( 'amp_post_template_footer', 'show_amp_ads' );

    (อย่าลืมแก้ตรง data-ad-client กับ data-ad-slot นะครับ ไม่งั้นเงินเข้าของผมหมดเลยนะ 55+)

หากต้องการใช้ Ads ตัวอื่นเช่น DoubleClick ให้ไปดูตัวอย่างจากที่นี่แล้วเอามาปรับครับ เช่นสมมุติของ DoubleClick จะเป็นประมาณนี้ครับ

<?php
function show_amp_ads(){
?>
<div style="text-align:center">
  <amp-ad width=320 height=50
      type="doubleclick"
      data-slot="/4119129/mobile_ad_banner"
      >
  </amp-ad>
</div>
<?php
}
add_action( 'amp_post_template_footer', 'show_amp_ads' );

จะเห็นว่าหลังจากใส่โคดลงไปจะเห็นว่ามีโฆษณาโผล่มาล่างสุดของหน้าเว็บแล้ว ถ้ามันไม่ขึ้นให้ลองดูผลสัก 2 – 3 วันนะครับ เพื่อให้ Bot Google เข้ามาเก็บข้อมูลไปหาว่าควรแสดงโฆษณาตัวใดดี

ข่าวร้ายสำหรับคนที่เดาโคดข้างต้นแล้วพยายามเปลี่ยนให้โฆษณาไปติดอยู่เหนือบทความ ขอบอกว่าแค่แก้ amp_post_template_footer เป็น amp_post_template_header ไม่ได้นะครับ เพราะมันไม่มี ผมลองแล้ว ถ้าอยากแก้ต้องไปแก้ที่ templates/single.php ที่อยู่ในโฟลเดอร์ plugin AMP ครับ

หากต้องการแก้ไขหน้า AMP เอง สามารถทำอย่างไรได้บ้าง

  1. คัดลอก templates/single.php ในโฟลเดอร์ plugin ไปไว้ที่ theme/amp/single.php
  2. เพิ่ม code ตรงนี้ลง functions.php
    <?php
    function my_amp_set_custom_template( $file, $type, $post ) {
        if ( 'single' === $type ) {
            $file = dirname( __FILE__ ) . '/amp/single.php';
        }
        return $file;
    }
    add_filter( 'amp_post_template_file', 'my_amp_set_custom_template', 10, 3 );
  3. แก้ amp/single.php ตามสะดวก แต่ต้องตรงมาตรฐาน AMP นะครับ จะใส่โฆษณาอะไรตรงไหนก็เต็มที่ครับ แต่ถ้าเยอะไปมันจะผิดวัตถุประสงค์ของ AMP นะครับ ระวังด้วย

WordPress ช้าเพราะ Really Simple CAPTCHA

อันนี้เอามาจากโพสนี้ ไม่ได้เจอเอง คิดว่าน่าจะแก้ได้แล้วเพราะเจ้าของโพสมากดไลค์ แต่ไม่แจ้งผล

really_simple_captcha_property

ปัญหาที่เกิดคือเค้าบอกว่าเว็บช้ามาก เพราะ Really Simple CAPTCHA และขนาดของ plugin ใหญ่มาก (พวก cache ภาพที่ gen แล้วต่างๆ) ตอนแรกผมไม่เชื่อเท่าไหร่ เพราะผมคิดว่ามันไม่น่าจะช้าได้จากตัวนี้ จนกระทั่ง เค้าใช้ P3 Profiler มาให้ดูจริงๆ ผมก็เลยไปลองไล่ดู Code

ผมเดาว่าสาเหตุนั้นมาจากตอน clean up พวกภาพที่หมดอายุต่างๆ ทำให้มันกิน resource จากตัวอย่างคือ loop อ่าน meta file 20000 กว่ารอบ เพื่อลบไฟล์ที่ไม่ใช้ (ยิ่งถ้าใช้พวก NFS นะ โคตรช้า)

Solution

  1. เปิดไฟล์ really-simple-captcha.php หา function cleanup ให้แก้ไขเป็นดังนี้
    	public function cleanup( $minutes = 60 ) {
    		return 0;
    	}

    (ปิดการทำงานของ clean up เพื่อไม่ให้เว็บช้า เราจะย้ายไปทำใน background แทน)

  2. ให้สร้างไฟล์ชื่อ cleanup.php ข้างๆ really-simple-captcha.php มีเนื้อความดังนี้
    <?php
    $minutes=60;
    $dir = trailingslashit( path_join( dirname( __FILE__ ), 'tmp' ) );
    $dir = str_replace( '\\', '/', $dir );
    $dir = preg_replace( '|/+|', '/', $dir );
     
    if ( ! @is_dir( $dir ) || ! @is_readable( $dir ) )
            return false;
     
    $is_win = ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) );
     
    if ( ! ( $is_win ? win_is_writable( $dir ) : @is_writable( $dir ) ) )
            return false;
     
    $count = 0;
     
    if ( $handle = @opendir( $dir ) ) {
            while ( false !== ( $filename = readdir( $handle ) ) ) {
                    if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $filename ) )
                            continue;
     
                    $file =  $dir . $filename ;
                    $file = str_replace( '\\', '/', $dir );
                    $file = preg_replace( '|/+|', '/', $dir );
     
                    $stat = @stat( $file );
                    if ( ( $stat['mtime'] + $minutes * 60 ) < time() ) {
                            @unlink( $file );
                            $count += 1;
                    }
            }
     
            closedir( $handle );
    }
     
    ?>

    (เป็นไฟล์สำหรับ clean up แบบ manual)

  3. สร้าง cronjob เพื่อสั่งให้ cleanup.php ทำงาน (หรือเข้ามาสั่งเองทุกวันก็ได้ แต่ถ้าสั่งช้า มันจะกินพื้นที่ HDD เยอะขึ้นเรื่อยๆ)

จบ เอาไปทดสอบได้เลยครับ

[บันทึก] นรก การกู้ WordPress แบบ DB ไม่ตรงกับกับเวอร์ชั่นไฟล์

เกริ่นนำก่อนคือ ผมเป็นโปรแกรมเมอร์แบบ Part time ให้กับเว็บไซต์เว็บหนึ่งซึ่งใหญ่พอสมควร คนเข้าระดับหลักหมื่นต่อวัน PageView ระดับ 2 แสนอับ ทำให้เค้าอยากให้ทำระบบ cache ขึ้นมาเอง (พวก plugin เค้าบอกใช้แล้วไม่ work) ซึ่งระบบนี้คือ cache แบบเป็น static file ทั้งหน้า บางส่วนที่เป็น comment ใช้ AJAX เอา( cache เหมือนกันด้วย เคลียเมื่อมีคน comment) โดย cache ส่วนอื่นที่ไม่ใช่ comment จะเคลียเมื่อถูกสั่งเท่านั้นไม่มีหมดเวลา ก็ใช่มาปีกว่าไม่มีปัญหา

ที นี้นรกเกิดเมื่อวันดีคืนดีไอ้ SSD ของ Server เจ้ากรรม แม่มเสือกพัง ทำให้ความซวยบังเกิดเพราะ backup ที่มีเป็นของ DB ตอนเดือน 5 แต่ตัว file ของ server ที่เคย backup ไว้มีของเดือน 2 ครับ (มีบางไฟล์ที่ได้ของเดือน 5 มา) ทีนี้พอเปิด server ปุป เข้าหน้าแรกเจอ 404 ภาพหายทั้งหน้า (555) แถมปัญหาเกิดทันที คือพอเว็บ run ขึ้นปุป โหลดพุ่งทันที ผมเลยตั้งประเด็นไปที่ cache ครับ ว่า ในระหว่าง 3 เดือนผมเคยไปทำไรมันรึเปล่า เนื่องจากไม่มีตัว version control ผลคืองมครับ ไม่ทราบว่ามันคืออะไรเกิดจากอะไร แต่เปิดปุปแม่มพัง

หลังจากงมไป ประมาณ 5 ชั่วโมง ว่าเป็นอะไรทำไม cache ไม่ทำงาน ผมดันกดผิดสิ่งที่ได้คือ หน้า 404 ผมเกิดความคิดบัดดลว่าไอ้เห้นี่แหละ ทำโหลดพุ่ง เพราะ cache ตัวนี้เนื่องจากไม่มีกำหนดเวลา ผมเลยไม่ cache 404 กลัวว่าถ้า cache ไปแล้วตอนหลังมีชื่อซ้ำมันจะเรียก cache ก่อน ทำให้การโหลด 404 ทั้งหมดต้องไป query DB เลยต้องดัก 404 ว่าไม่ต้องทำอะไรทั้งนั้นครับ เรื่องถึงได้จบ โหลดร่วงอย่างไว นั่งทำตั้งนาน