• Skip to main content

MrHói's Blog

The simple is the best

You are here: Home / Archives for SELECT

SELECT

Khắc phục việc treo wordpress khi chưa kịp thực hiện các lệnh pingback hoặc trackback

July 15, 2013 by mrhoi Leave a Comment

Trong khi sử dung wordpress, với dữ liệu khổng lồ hằng ngày đổ vào hệ thống, kết hợp với khả năng pingback và trackback tự động của WordPress, nột điểm khá thú vị của WordPress và tốt cho SEO, nhưng cũng đem lại phiền toái không nhỏ với người quản trị hệ thống.

Vậy có vấn đề gì xảy ra, tôi không muốn nói tới việc bạn để WordPress chạy Cron Job khi người dùng truy cập website… kể cả khi bạn đã tắt tình năng này và sử dụng chạy WordPress Cron Job thủ công với crontab trên Unix (nếu bạn chưa tôi ưu hiệu xuất của wordpress theo cách này… hãy đón chờ bài viết giời thiệu tính năng này trên blog của tôi trong một vài ngày tới nhé).

Trở lại với tình huống trên, thú thật là khi chuyển đổi Server cho ứng dụng của mình, tôi đã quên bật Crontab thực hiện chức năng chạy thủ công, để thực hiện các CronJob của WordPress… nên hệ thống của tôi xảy ra tình trạng tồn đọng các lệnh pingback và trackback cần thiết phải xử lý. Tất nhiên khi tôi nhớ ra điều này thì khối lượng lệnh tồn đọng đã chiếm một số lượng rất lớn. Hệ thống của tôi trở nên ỳ ạch mỗi khi crontab thủ công kia tiến hành.

Và sau đây là đoạn mã nguồn tôi tìm được và tiến hành xử lý trong file wp-includescomment.php

function do_all_pings() {

global $wpdb;

// Do pingbacks

while ($ping = $wpdb->get_row(“SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = ‘_pingme’ LIMIT 1″)) { delete_metadata_by_mid( ‘post’, $ping->meta_id ); pingback( $ping->post_content, $ping->ID ); }

// Do Enclosures

while ($enclosure = $wpdb->get_row(“SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = ‘_encloseme’ LIMIT 1”)) { delete_metadata_by_mid( ‘post’, $enclosure->meta_id ); do_enclose( $enclosure->post_content, $enclosure->ID ); }

// Do Trackbacks

$trackbacks = $wpdb->get_col(“SELECT ID FROM $wpdb->posts WHERE to_ping ” AND post_status = ‘publish'”);

if ( is_array($trackbacks) )

foreach ( $trackbacks as $trackback )

do_trackbacks($trackback);

//Do Update Services/Generic Pings

generic_ping();

}

Các bạn chú ý những dòng được bôi đậm, hệ thống sẽ tiến hành thực hiện hàng trăm, ngàn câu lệnh tìm kiếm những bản ghi phù hợp, ghi nhận việc phải pingback / trackback để thực hiện… Giải pháp của tôi là bắt hệ thống xử lý dần dần với việc giới hạn lại số lượng post cần xử lý mỗi khi thực hiện… ở đây tôi lấy luôn số lượng post hiển thị ở trang chủ làm giới hạn của việc này. Thực tế nếu hệ thống của bạn chạy thường xuyên thì việc trên không dẫn đến việc nghẽn hệ thống… nhưng nếu bạn gặp trường hợp giống tôi… hi vọng bạn có thể tham khảo các xứ lý này.

function do_all_pings() {

global $wpdb;

// get limit of post per page

$limit = get_option(‘posts_per_page’, 10);

$limit = $limit * 50;

// Do pingbacks

$pings = $wpdb->get_results($wpdb->prepare(“SELECT meta_id, post_id FROM {$wpdb->postmeta} WHERE meta_key = ‘_pingme’ LIMIT %d”, $limit));

if (is_array($pings)) {

foreach ($pings as $ping) {

$post_id = $ping->post_id;

$post = get_post($post_id);

delete_metadata_by_mid( ‘post’, $ping->meta_id );

//pingback( $ping->post_content, $ping->ID );

pingback( $post->post_content, $post->ID );

}

}

// Do Enclosures

$enclosures = $wpdb->get_results($wpdb->prepare(“SELECT meta_id, post_id FROM {$wpdb->postmeta} WHERE meta_key = ‘_encloseme’ LIMIT %d”, $limit));

if (is_array($enclosures)) {

foreach($enclosures as $enclosure) {

$post_id = $enclosure->post_id;

$post = get_post($post_id);

delete_metadata_by_mid( ‘post’, $enclosure->meta_id );

//do_enclose( $enclosure->post_content, $enclosure->ID );

do_enclose( $post->post_content, $post->ID );

}

}

// Do Trackbacks

$trackbacks = $wpdb->get_col($wpdb->prepare(“SELECT ID FROM $wpdb->posts WHERE to_ping ” AND post_status = ‘publish’ LIMIT %d”, $limit));

if ( is_array($trackbacks) )

foreach ( $trackbacks as $trackback )

do_trackbacks($trackback);

//Do Update Services/Generic Pings

generic_ping();

}

Chúc các bạn thành công.

Filed Under: Hệ thống, Wordpress Tagged With: 'post', 'posts_per_page', AND post_status = 'publish', Cron Job, CronJob, Do Enclosures, Do Trackbacks, Do Update Services, dPress Cron Job, FROM, Generic Pings, LIMIT, post_content, SELECT, SELECT ID, SELECT ID FROM, WHERE, Wordpress Cron Job

Tối ưu xử lý wordpress với dữ liệu lớn khi thêm mới bài viết

July 14, 2013 by mrhoi 2 Comments

Nếu bạn sử dụng wordpress để triển khai một tờ báo điện tử, hay đơn giản để thử nghiệm với hệ thống với khối lượng dữ liệu lớn, tôi nghĩ bạn sẽ gặp một trường hợp giống như tôi, đó là việc hệ thống xử lý rất chậm và quá tải khi lượng bài viết được cập nhật thường xuyên và liên tục.

Sau khi xem các slow query của MySQL, tôi chợt nhật thấy một điểm đó là khi cập nhật nội dung hệ thông sẽ tự cập nhật tổng số các bài viết thuộc taxonomy mà bài viết đó sử dụng…. sẽ không thành vấn đề lớn, nếu dữ liệu bạn nhỏ, nhưng với lượng dữ liệu khổng lồ thì vấn đề sẽ nằm ở tốc độ truy vấn và tạo ra một câu lệnh Join khổng lồ với cú pháp gốc của WordPress. Mã nguồn được thay đổi tại thư mục wp-includes/taxonomy.php

if ( $object_types )

$count += (int) $wpdb->get_var( $wpdb->prepare( “SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = ‘publish’ AND post_type IN (‘” . implode(“‘, ‘”, $object_types ) . “‘) AND term_taxonomy_id = %d”, $term ) );

Với cú pháp trên, số lượng bảng ghi được tạo trong lệnh trên sẽ là tổ hợp của bảng Post và bảng team_relationships, sẽ là vấn đề nếu dữ liệu post và tag của bạn khá lớn.

Các giải quyết của tôi, sử dụng lệnh LEFT JOIN, để hạn chế lại những bản ghi term_relationships phù hợp với yêu cầu thuật toán, thay vì lấy hết ra rồi mới lọc

if ( $object_types )

$count += (int) $wpdb->get_var( $wpdb->prepare( “SELECT COUNT(*) FROM $wpdb->term_relationships LEFT JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = ‘publish’ AND post_type IN (‘” . implode(“‘, ‘”, $object_types ) . “‘) WHERE term_taxonomy_id = %d”, $term ) );

Hi vọng nếu bạn gặp trường hợp giống như tôi, có thể giựa vào gợi ý trên để tối ưu hóa hệ thống cho mình.

Còn với tôi, tôi cũng ghi chép ra đây để thay đổi lại mỗi khi cập nhật phiên bản mới của wordpress.

Chúc bạn thành công.

Filed Under: Wordpress Tagged With: cập nhật, COUNT, FROM, JOIN, LEFT, Left Join, SELECT, SELECT COUNT, WHERE

Khắc phục tình trạng không hiển thị phân trang trên WordPress với Hostgator

August 26, 2011 by mrhoi 3 Comments

Nếu bạn là người đã sử dụng wordpress trên hostgator, cũng ngịch ngầm và chỉnh sửa các thông số của PHP, thì rất có thể sẽ gặp tình trạng giống như tôi. Một ngày đẹp trời hệ thống vẫn chạy bình thường nhưng không thể tìm thấy các trang tiếp theo để click. Nguyên nhân ở đâu?

Sau một buổi tối ngồi hỳ hục tìm hiểu chỉnh sửa, tôi đã hiển thị được số trang cần theo một cách nông dân là debug từng dòng lệnh. Nhưng để rồi có một kiến thức mới hay ho không kém. Cái tội là WordPress sử dụng hàm FOUND_ROWS() để tính số lượng bản ghi nếu không có giới hạn LIMIT. Nhược điểm chính của việc này là dòng lệnh trên phải được xử lý ngay sau khi câu SELECT được thực hiện.

Tại sao hệ thống lại chạy không chỉnh xác khi tôi thay đổi config của PHP, lý do là tôi muốn kiểm tra hệ thống sẽ hoạt động ra sao khi vận hành, việc cần biết đó là nó truy vấn tới database ra sao. Tôi đã chỉnh sửa một số thiết lập của PHP trong đó có mysql.allow_persistent, điều này đã làm cho câu lệnh FOUND_ROWS() luôn trả về giá trị là 1, vì đơn giản sau khi thực hiện lệnh hệ thông sẽ truy vấn thêm log của MySQL ghi ra log file, tất nhiên những truy vấn này đều có 1 kết quả trả về.

Tiếp đó hệ thống của WordPress luôn tín sai và duy nhất chỉ có một trang. Cả buổi tối ngày hôm đó tôi loay hoay và cũng chỉnh sửa được bằng cách viết 1 hàm hook vào wordpress để thay đổi cách thức tính số trang, không sử dụng FOUND_ROWS() nữa. Các bạn gặp trường hợp trên tạm thời muốn chạy có thể sử dụng hàm này:

add_filter(‘found_posts_query’, ‘wpspider_fix_max_num_pages’);

function wpspider_fix_max_num_pages ($query) {

global $wp_query;

if ($query == ” || $query != ‘SELECT FOUND_ROWS()’) return $query;

$query = $wp_query->request;

$query = preg_replace(‘/SELECT\s.+\sFROM/’, ‘SELECT 1 as id FROM’, $query);

$query = preg_replace(‘/LIMIT\s.+$/’, ”, $query);

$query = preg_replace(‘/ORDER\s+BY\s.+$/’, ”, $query);

$query = sprintf(‘SELECT SUM(id) FROM (%1$s) as `count` ‘, $query);

return $query;

}

Hơi ngu ngốc một chút vì thỉnh thoảng hệ thống có phun ra một số log error query vì câu lệnh SQL không chính xác, nhưng sẽ là tạm đủ khi bạn vừa muốn debug hệ thống vừa muốn hệ thống hoạt động bình thường.

Filed Under: Hệ thống, Lập trình, Wordpress Tagged With: 'found_posts_query', 'SELECT 1 as id FROM', 'wpspider_fix_max_num_pages', FOUND, FROM, Hostgator Nếu, LIMIT, ORDER, ROWS, SELECT, SELECT FOUND, SELECT FOUND_ROWS, SELECT SUM, wordpress

Copyright © 2026 · Revolution Pro on Genesis Framework · WordPress · Log in