วิธีเพิ่มประสิทธิภาพเว็บไซต์ WP สำหรับโพสต์นับล้าน


19

ฉันกำลังทำงานกับเว็บไซต์ของ บริษัท ที่มีแนวโน้มที่จะสร้างโพสต์นับล้านผ่านประเภทโพสต์ที่กำหนดเอง พวกเขากำลังสวดอ้อนวอนดังนั้นโดยทั่วไปผู้ใช้ส่วนหน้าเพียงแค่ส่งวลีสั้น ๆ ผ่านแบบฟอร์ม บริษัท ทั้งหมดให้ความสำคัญกับเนื้อหาโพสต์และวันที่โพสต์ ไซต์ยังไม่ได้เปิดตัวและพวกเขามีโพสต์มากกว่า 120,000 รายการดังนั้นฉันจึงตายอย่างจริงจังเมื่อฉันพูดเป็นล้าน

ดังนั้นคำถามการเพิ่มประสิทธิภาพคู่:

  1. สมมติว่าฉันมีหมวดหมู่ "เด่น" ในประเภทโพสต์ที่กำหนดเองที่มี 500,000 โพสต์ หมวดหมู่เรื่องเด่นมีเพียง 500 โพสต์ หากฉันสร้างการสืบค้นสำหรับโพสต์เด่นฉันจะทำการค้นหาทั้ง 500,000 โพสต์หรือเฉพาะ 500 โพสต์ จะทำอย่างไรถ้าฉันต้องการแสดงเฉพาะสิบโพสต์ล่าสุดที่โพสต์ไว้
  2. เมื่อบันทึกประเภทโพสต์ที่กำหนดเองนี้ไปยังฐานข้อมูลมีสิ่งใดบ้างที่ฉันสามารถทำได้เพื่อลดทรัพยากรของเซิร์ฟเวอร์โดยเฉพาะอย่างยิ่งเนื่องจากสิ่งเดียวที่จำเป็นจริงๆคือเนื้อหาของโพสต์และวันที่?
  3. ฉันควรจะใช้ประเภทโพสต์ที่กำหนดเองหรือไม่ ฉันชอบในหลักการเพราะมันรวมเข้ากับผู้ดูแลระบบ WordPress ได้ดี แต่ถ้ามีข้อเสียเปรียบอย่างมากในการทำงานฉันคิดว่าฉันสามารถทำอะไรที่แตกต่างออกไปได้

ฉันไม่เคยทำงานเกี่ยวกับโครงการในระดับนี้ดังนั้นฉันจึงกังวลเกี่ยวกับประสิทธิภาพมากกว่าปกติ ขอบคุณสำหรับความช่วยเหลือใด ๆ !


เป็นสิ่งสำคัญที่จะต้องรักษาฐานข้อมูลให้น้อยที่สุดในฟังก์ชัน WordPress และสคริปต์การโทรอย่างเหมาะสม แต่ส่วนใหญ่ของการเพิ่มประสิทธิภาพนั้นเกี่ยวข้องกับวิธีการตั้งค่าและกำหนดค่าเซิร์ฟเวอร์ เพื่อค้นหาเครือข่าย Server Fault serverfault.com/search?q=optimize+wordpress
iyrin

@ RyanLoremIpsum - ขอบคุณสำหรับความคิดเห็น แต่ฉันหวังว่าจะตอบคำถามเฉพาะของฉัน สิ่งที่ฉันพบส่วนใหญ่นั้นเกี่ยวข้องกับเซิร์ฟเวอร์ไม่ใช่วิธีการทำงานของ WordPress และวิธีเพิ่มประสิทธิภาพจากมุมมองโค้ด
Jeremiah Prummer

คำตอบ:


26

1. ตั้งค่าคิวรีก่อนที่จะรัน WP_Query

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

ปกติแบบสอบถาม
สำหรับแบบสอบถามปกติ WordPress ใช้ฟังก์ชั่นซึ่งในการเปิดสายwp() $wp->main( $query_vars )"ตัวแปร is_" จากแท็กแบบมีเงื่อนไขจะถูกตั้งค่าก่อนที่จะส่งไปยังWP_Query->get_posts()ซึ่งจะแปลงเป็นแบบสอบถามฐานข้อมูล MySQL และในที่สุดก็เก็บไว้ในวัตถุ $ wp_query มันเป็นไปได้ที่จะกรองแบบสอบถามก่อนที่จะมีการเรียกใช้จริงในฐานข้อมูล SQL

pre_get_postsกระทำ hooks WP_Query->get_posts()เข้าสู่กระบวนการนี้ช่วยให้คุณสามารถเปลี่ยนแบบสอบถามก่อนที่มันจะถูกส่งไปยัง

ตัวอย่างเช่นหากคุณต้องการกรองข้อความค้นหาสำหรับโพสต์ในหมวดหมู่ "วิดีโอเด่น" คุณจะต้องใช้add_action( 'pre_get_posts', 'your_function_name' );และรวมin_categoryแท็กที่มีเงื่อนไขไว้your_function_nameด้วย

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Replace 123 with the category ID of the featured category.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

ดูปลั๊กอิน API / ข้อมูลอ้างอิงการกระทำ / รับโพสต์ก่อนหน้า« WordPress Codex

การร้องขอหน้า
สำหรับเทมเพลตหน้าเช่นหน้าการเก็บถาวรสำหรับหมวดหมู่ "คุณสมบัติ" แท็กแบบมีเงื่อนไขจะไม่ทำงานจากpre_get_postsตัวกรอง ตัวอย่างเช่นคุณไม่สามารถใช้is_categoryเพื่อตรวจสอบหน้าเก็บถาวรเพราะ WP_Query ไม่ได้ทำงาน

แต่คุณจะต้องเปลี่ยนข้อความค้นหาหลักสำหรับคำขอหน้าเว็บที่มีnew WP_Queryหน้าตาคล้าย$query = new WP_Query( 'cat=123' );กัน สิ่งนี้จะทำการสืบค้นด้วยชุดอาร์กิวเมนต์ที่เหมาะสมตั้งแต่เริ่มต้น

ดูClass Reference / WP Query « WordPress Codex

2. บันทึกลงในฐานข้อมูล

คุณสามารถใช้ตัวกรองwp_insert_post_dataเพื่อให้มั่นใจว่าเพียง $ wp_insert_postข้อมูลที่เกี่ยวข้องกับประเภทโพสต์ที่กำหนดเองของคุณจะถูกส่งกลับไปยัง ตรวจสอบให้แน่ใจว่าได้รวมคำสั่งแบบมีเงื่อนไขเพื่อตรวจสอบประเภทโพสต์ที่คุณกำหนดเอง
ปลั๊กอิน API / อ้างอิงตัวกรอง / wp แทรกข้อมูลโพสต์« WordPress Codex

เบ็ดนี้เรียกว่าโดยwp_insert_postฟังก์ชั่นซึ่งเรียกว่าโดยwp_update_postเมื่อคุณอัปเดตประเภทโพสต์ที่คุณกำหนดเองโดยปกติจะบันทึกร่างจดหมายหรือเผยแพร่โพสต์

คุณจะต้องสร้างมาตรฐานด้วยตัวเองแม้ว่าฉันจะไม่สามารถพูดถึงความสำคัญในการเพิ่มประสิทธิภาพของการลดข้อมูลที่อัพเดทในฐานข้อมูล

3. ประเภทโพสต์ที่กำหนดเองมีผลต่อประสิทธิภาพหรือไม่

จากประสบการณ์ของฉันประเภทโพสต์ที่กำหนดเองเป็นเครื่องมือที่มีประสิทธิภาพสำหรับการจัดการเนื้อหา ฉันไม่ทราบวิธีอื่นใดในการจัดการโพสต์ในทุกรูปแบบที่อนุญาตในลักษณะที่จะใช้ทรัพยากรน้อยลง ฉันจะมุ่งเน้นไปที่การหาวิธีที่จะลดจำนวนการค้นหาตามที่เป็นไปได้

เคยมีปัญหาด้านประสิทธิภาพที่เกี่ยวข้องกับโครงสร้าง Permalink ทำให้มันฮิตเมื่อเริ่มต้นด้วยข้อความแทนที่จะเป็นตัวเลข 3สิ่งนี้เป็นปัญหาโดยเฉพาะอย่างยิ่งสำหรับเว็บไซต์ที่โฮสต์หน้าจำนวนมาก แต่ได้รับการแก้ไขตั้งแต่รุ่น WordPress 3.3

ฉันเพิ่งจะเพิ่มลิงก์ถาวรที่นี่เพราะกระสุนมักจะเป็นส่วนแรกของโครงสร้างลิงก์ซึ่งอาจหรืออาจไม่ได้รับผลกระทบต่อประสิทธิภาพการทำงานก่อนรุ่น 3.3 นอกเหนือจากนั้นฉันไม่ทราบถึงปัญหาประสิทธิภาพใด ๆ ที่เกิดขึ้นจากการใช้โพสต์แบบกำหนดเอง

ตัวเลือกประสิทธิภาพอื่น ๆ

Transients
นี่ไม่ใช่การแทนที่เพื่อรักษาข้อความค้นหาให้น้อยที่สุดในรหัสของคุณ แต่คุณสามารถใช้set_transientเพื่อจัดเก็บแบบสอบถามในบางครั้งเพื่อให้แบบสอบถามใหม่ไม่จำเป็น นี่คือตัวอย่างที่ใช้ในการเดฟเคลเมนท์โพสต์ นอกจากนี้โปรดทราบว่าเขาแนะนำให้เพิ่มการsave_postกระทำเพื่อลบชั่วคราวเมื่อใดก็ตามที่มีการอัปเดตประเภทโพสต์ที่กำหนด

<?php // IN THE SPOTLIGHT QUERY
if( false === ( $its_query = get_transient( 'its_query' ) ) ) {
    $pttimestamp = time() + get_option('gmt_offset') * 60*60;
    $its_query = new WP_Query( array(
        'post_type' => 'spotlight',
        'posts_per_page' => 1,
            'post__not_in' => $do_not_duplicate,
        'meta_query' => array(
            array(
                'key' => '_hpc_spotlight_end_time',
                'value' => $pttimestamp,
                'compare' => '>'
            )
        )
    ) );
    set_transient( 'its_query', $its_query, 60*60*4 );
}
if( have_posts() ) { // HIDE SECTION IF NO CURRENT ITS FEATURE ?>
    // LOOP GOES HERE: NOT IMPORTANT TO EXAMPLE
<?php } ?>

การเพิ่มประสิทธิภาพการค้นหาเพิ่มเติม
Thomas Griffin มีเคล็ดลับดี ๆ บางส่วนในบทช่วยสอนการเพิ่มประสิทธิภาพ WordPressของเขา นี่คือรายการสั้น ๆ ของคำแนะนำของเขา:

  • ตั้งค่า'cache_results' => falseในแบบสอบถามแบบใช้ครั้งเดียวหากเซิร์ฟเวอร์ของคุณไม่ได้ใช้แคชถาวรเช่น Memcached แบบสอบถามแบบใช้ครั้งเดียวมีคำอธิบายว่า "แบบสอบถามที่ใช้ในการแสดงข้อมูลจำนวนเล็กน้อยอาจเป็นได้ว่าคุณเพียงแค่ต้องการแสดงชื่อโพสต์ที่เชื่อมโยงที่เกี่ยวข้องกับโพสต์ปัจจุบันหรือคุณอาจต้องการแสดงรายการแบบเลื่อนลงเพื่อเลือก การตั้งค่าตัวเลือกเฉพาะ "

    ตัวอย่างของเขา: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • ตั้งค่า'no_found_rows' => trueที่ไม่ต้องการเลขหน้า สิ่งนี้จะ "เลี่ยง MySQL ที่จะนับผลลัพธ์เพื่อดูว่าเราต้องการเลขหน้าหรือไม่"

    ตัวอย่างของเขา: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • คำถามสำหรับรหัสโพสต์เพียงว่านี่คือสิ่งที่คุณต้องการใน'fields' => 'ids' get_postsสิ่งนี้ควรลดจำนวนข้อมูลที่จะถูกส่งคืนซึ่งค่อนข้างมากต่อการโพสต์ถ้าคุณดูที่ คำอธิบายฐานข้อมูล« WordPress Codex

    ตัวอย่างของเขา: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

นอกจากนั้นปลายที่ผ่านมาเหตุผลเดียวกันสามารถนำไปใช้เมื่อคุณต้องการเพียงหนึ่งหรือโพสต์ไม่กี่สาขาโดยใช้get_post_field

การมีความเข้าใจอย่างถ่องแท้เกี่ยวกับการทำงานของแบบสอบถามเป็นสิ่งจำเป็น ยิ่งคุณมีข้อสงสัยมากเท่าไหร่คุณก็ยิ่งต้องการงานจากฐานข้อมูล SQL น้อยลงเท่านั้น ซึ่งหมายความว่ามีความเป็นไปได้มากมายสำหรับการจัดการคิวรีของฐานข้อมูล ระมัดระวังแบบสอบถามที่กำหนดเองเท่าที่พวกเขาเรียกใช้ (มันเป็นหน้าผู้ดูแลระบบหรือไม่) ใช้การฆ่าเชื้อที่เหมาะสมในการสอบถามโดยตรงและพยายามใช้ฟังก์ชั่น WordPress ดั้งเดิมที่ช่วยให้คุณบรรลุประสิทธิภาพเดียวกัน


2
คำตอบที่ยอดเยี่ยมและเป็นประโยชน์อย่างมากขอบคุณ!
Jeremiah Prummer

ชุดรูปแบบถูกสร้างขึ้นเองทั้งหมดดังนั้นเราจึงเป็นเพียงการสอบถามรายการที่จำเป็นอย่างยิ่งเท่านั้น สิ่งเหล่านี้มีประโยชน์มาก รับนี้ฉันจะกลับไปและทำการเปลี่ยนแปลงบางอย่างของแบบสอบถามของฉัน ;)
Jeremiah Prummer

1
ฉันต้องการเพิ่มว่าคุณควรหลีกเลี่ยงการสืบค้นเมตาเมื่อเป็นไปได้ ไม่ต้องเรียกใช้แบบสอบถามกับเขตข้อมูลเมตาสองแห่งพร้อมกัน สิ่งนี้ส่งผลให้มีการสืบค้นสองและสามซึ่งกลายเป็นประสิทธิภาพ nigtmare อย่างรวดเร็ว ประเภทโพสต์ที่กำหนดเองมักจะช่วยได้
Charles Jaimet

3

ฉันยังเพิ่ม:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (บูลีน) - ทำให้เป็นจริงเมื่อคุณไม่ต้องการการแบ่งหน้าใด ๆ และไม่ต้องการการนับจำนวนโพสต์ทั้งหมดที่พบ
  • cache_results (บูลีน) - โพสต์แคชข้อมูล
  • update_post_meta_cache (บูลีน) - โพสต์แคชข้อมูลเมตา
  • update_post_term_cache (บูลีน) - โพสต์ข้อมูลแคช

ด้วยการใช้พารามิเตอร์เหล่านี้และส่งผ่านค่าเป็น FALSE เราสามารถทำให้แบบสอบถามเร็วขึ้นโดยหยุดการสืบค้นฐานข้อมูลเพิ่มเติมบางส่วนที่จะดำเนินการ

หมายเหตุ: เราไม่ควรใช้พารามิเตอร์เหล่านี้เสมอเนื่องจากการเพิ่มสิ่งต่าง ๆ ลงในแคชเป็นสิ่งที่ถูกต้องอย่างไรก็ตามสิ่งเหล่านี้อาจมีประโยชน์ในบางสถานการณ์และคุณควรพิจารณาใช้เมื่อคุณรู้ว่าคุณกำลังทำอะไร

กรุณาเยี่ยมชม: https://drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184


1
โปรดแก้ไขคำตอบของคุณและเพิ่มคำอธิบาย: เหตุใดจึงแก้ไขปัญหาได้
fuxia

ฉันไม่สามารถเพิ่มความคิดเห็นในคำตอบนี้: wordpress.stackexchange.com/a/166699/57674
rigosan

1

เนื่องจากคำถามประเภทการปรับให้เหมาะสมก่อนกำหนดทั้งหมดไม่สามารถตอบคำถามนี้ได้จริงโดยไม่ทราบรูปแบบการใช้งานที่แน่นอนซึ่งมีการค้นพบหลายครั้งมากเกินไปเฉพาะเมื่อคุณใช้งานจริง

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

คุณอาจต้องการปรับวิธีการจัดเก็บข้อมูลเมตา (ตัวอย่างเช่นไม่จัดเก็บข้อมูลที่เกี่ยวข้องกับการปิง) แต่สิ่งประเภทนี้ขึ้นอยู่กับสิ่งที่คุณทำและในที่สุดคุณอาจต้องใช้ CPU ที่แข็งแกร่งกว่าดังนั้นอาจไม่คุ้มกับปัญหาของคุณ .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.