Hiểu và tối ưu WordPress Query: WP_Query, get_posts và $wpdb

Truy vấn dữ liệu trong WordPress có nhiều cách khác nhau. Nhưng không phải cách nào cũng tối ưu cho mọi tình huống. Việc lựa chọn sai phương pháp có thể dẫn đến hiệu năng kém, query thừa và thậm chí làm chậm cả website. Bài viết này phân tích sự khác nhau giữa WP_Query, get_posts$wpdb, kèm hướng dẫn cách dùng hợp lý để tối ưu performance.

Hiểu và tối ưu WordPress Query: WP_Query, get_posts và $wpdb

Khi nào dùng WP_Query?

WP_Query là class mạnh mẽ và linh hoạt nhất trong WordPress. Nó cho phép bạn truy vấn post theo hầu hết tiêu chí (post type, taxonomy, meta, order, paginate…). Tuy nhiên, WP_Query cũng là công cụ “nặng” nhất vì nó xử lý rất nhiều logic nội bộ.

<?php
$query = new WP_Query([
    'post_type'      => 'post',
    'posts_per_page' => 10,
    'paged'          => get_query_var('paged', 1),
]);

if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();
        the_title('<h2>', '</h2>');
    }
    wp_reset_postdata();
}
?>

Sử dụng WP_Query khi bạn cần phân trang, query phức tạp với nhiều tham số, hoặc muốn hook vào các filter có sẵn.

Khi nào dùng get_posts?

get_posts() thực chất là một wrapper của WP_Query, nhưng đã bật sẵn vài option tối ưu: no_found_rows = true, update_post_meta_cache = false, update_post_term_cache = false. Nghĩa là nó nhẹ hơn khi bạn chỉ cần danh sách post mà không cần phân trang hoặc tính toán tổng số trang.

<?php
$posts = get_posts([
    'post_type'      => 'page',
    'posts_per_page' => 5,
    'orderby'        => 'date',
    'order'          => 'DESC',
]);

foreach ( $posts as $post ) {
    setup_postdata($post);
    echo '<h3>' . esc_html( get_the_title($post) ) . '</h3>';
}
wp_reset_postdata();
?>

Sử dụng get_posts() khi chỉ cần lấy một số lượng nhỏ post, không phân trang, không cần tính tổng số trang.

Khi nào dùng $wpdb?

$wpdb cho phép bạn chạy query SQL trực tiếp trên database. Đây là cách nhanh nhất, nhưng cũng dễ sai và bỏ qua nhiều layer bảo mật, cache của WordPress. Dùng khi bạn cần query đặc biệt mà WP_Query không đáp ứng, hoặc khi cần join nhiều bảng.

<?php
global $wpdb;
$results = $wpdb->get_results( $wpdb->prepare(
    "SELECT ID, post_title FROM {$wpdb->posts}
     WHERE post_type = %s AND post_status = %s
     ORDER BY post_date DESC
     LIMIT %d",
    'post', 'publish', 5
) );

foreach ( $results as $row ) {
    echo '<p>' . esc_html( $row->post_title ) . '</p>';
}
?>

Sử dụng $wpdb khi bạn cần hiệu năng cao, join dữ liệu phức tạp, hoặc báo cáo tổng hợp. Luôn nhớ dùng $wpdb->prepare() để tránh SQL injection.

So sánh hiệu năng: WP_Query vs get_posts vs $wpdb

Phương pháp Hiệu năng Khi nên dùng Khi tránh dùng
WP_Query Chậm nhất (nhiều layer xử lý) Phân trang, query phức tạp Lấy danh sách nhẹ, không paginate
get_posts Nhanh hơn WP_Query Lấy ít post, không cần found rows Lúc cần template tag multi-loop
$wpdb Nhanh nhất Join bảng, báo cáo, logic đặc biệt Khi WP_Query đủ dùng và an toàn hơn

Tối ưu meta_query và tax_query

Đây là yếu tố ảnh hưởng lớn nhất đến tốc độ WP_Query. Một số tối ưu bạn nên áp dụng:

  • Tránh meta_query dạng LIKE vì gây full table scan.
  • Thêm index cho meta_key nếu lọc thường xuyên.
  • Giảm số lượng meta_query lồng nhau.
  • Với tax_query, tránh query quá nhiều term cùng lúc.

Sử dụng cache để tăng tốc Query

Những query nặng hoặc lặp lại nhiều lần nên được cache để giảm tải database.

<?php
global $wpdb;

$cache_key = 'home_latest_posts_sql';
$data = wp_cache_get( $cache_key );

if ( false === $data ) {

    // Query trực tiếp bằng SQL, tối ưu hơn get_posts khi chỉ cần dữ liệu cơ bản
    $sql = "
        SELECT ID, post_title 
        FROM {$wpdb->posts}
        WHERE post_type = 'post'
          AND post_status = 'publish'
        ORDER BY post_date DESC
        LIMIT 10
    ";

    $rows = $wpdb->get_results( $sql );

    // Chuẩn hóa dữ liệu để dễ dùng ở template
    $data = array_map( function( $row ) {
        return [
            'id'    => (int) $row->ID,
            'title' => $row->post_title,
            'url'   => get_permalink( $row->ID ),
        ];
    }, $rows );

    wp_cache_set( $cache_key, $data, '', 300 ); // cache 5 phút
}

foreach ( $data as $post ) {
    echo '<p><a href="' . esc_url( $post['url'] ) . '">' 
         . esc_html( $post['title'] ) . '</a></p>';
}
?>

Cache đúng cách có thể giảm 50% – 80% số lượng query SQL.

Những sai lầm phổ biến khiến WordPress Query chậm

  • Dùng posts_per_page = -1 ở site có dữ liệu lớn.
  • Meta_query phức tạp hoặc dùng LIKE.
  • Không bật no_found_rows khi không phân trang.
  • Dùng WP_Query trong loop mà không reset.
  • Dùng $wpdb trực tiếp nhưng không cache.

Chọn phương pháp nào? – Hướng dẫn nhanh

  • Dùng WP_Query khi cần phân trang hoặc điều kiện lọc phức tạp.
  • Dùng get_posts khi cần danh sách nhỏ và nhẹ.
  • Dùng $wpdb khi cần SQL nâng cao hoặc hiệu năng cao.
  • Dùng cache cho những truy vấn nặng hoặc lặp lại.

Kết luận

Không có phương pháp truy vấn nào phù hợp cho mọi tình huống. WP_Query mạnh nhưng nặng, get_posts nhanh và gọn, còn $wpdb cho bạn hiệu năng tối đa nhưng yêu cầu hiểu rõ database.

Hãy chọn đúng công cụ theo yêu cầu và tối ưu thêm bằng cache, no_found_rows, fields = ‘ids’, và hạn chế meta_query phức tạp. Đây là cách đơn giản nhưng hiệu quả để tăng tốc toàn bộ hệ thống WordPress.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...