使用stats_get_csv获取文章浏览量致CSV导出速度极慢,求解决方案
解决WordPress CSV导出时Jetpack浏览量获取速度过慢的问题
问题根源
你当前的核心瓶颈是循环调用stats_get_csv单篇请求浏览量,这个函数每次调用可能涉及远程请求Jetpack服务器或低效的单条查询,哪怕有缓存,首次批量导出时仍需逐个处理,直接拖慢了导出速度。
有效解决方案
1. 批量获取所有文章的浏览量(优先推荐)
放弃单篇请求逻辑,一次性拉取全量文章的浏览数据,存入内存数组供导出循环直接取用,彻底避免多次IO/远程请求:
// 新增批量获取所有文章浏览量的函数 function get_all_post_views() { $cache_key = 'all_post_views'; $all_views = wp_cache_get($cache_key); if ($all_views === false && function_exists('stats_get_csv')) { // 一次性获取所有文章的总浏览量 $args = array( 'days' => -1, 'limit' => -1 ); $results = stats_get_csv('postviews', $args); $all_views = array(); foreach ($results as $item) { $post_id = intval($item['post_id']); $all_views[$post_id] = intval($item['views']); } // 延长缓存有效期至1小时,浏览量无需实时更新 wp_cache_set($cache_key, $all_views, 'post_views', 3600); } return $all_views ?: array(); }
修改导出循环代码:
// 先批量获取所有浏览量数据 $all_post_views = get_all_post_views(); foreach ($results as $post) { // 直接从批量数组中取值,无需再调用单篇查询函数 $views = isset($all_post_views[$post->ID]) ? $all_post_views[$post->ID] : 0; fputcsv($output, array( $post->ID, $post->post_title, get_the_author_meta('display_name', $post->post_author), implode(', ', wp_get_post_categories($post->ID, ['fields' => 'names'])), $views, $post->post_date, )); ob_flush(); flush(); }
2. 直接读取Jetpack本地统计数据表(性能最优)
Jetpack会将统计数据同步到本地数据库,通常表名为wp_jetpack_post_views(前缀随你的WordPress设置调整),直接通过SQL批量查询,跳过Jetpack的API调用逻辑:
function get_all_post_views_from_db() { global $wpdb; $cache_key = 'all_post_views_db'; $all_views = wp_cache_get($cache_key); if ($all_views === false) { $table_name = $wpdb->prefix . 'jetpack_post_views'; // 按文章ID分组累加每日浏览量,和stats_get_csv返回结果逻辑一致 $results = $wpdb->get_results( "SELECT post_id, SUM(views) as total_views FROM $table_name GROUP BY post_id", ARRAY_A ); $all_views = array(); foreach ($results as $item) { $post_id = intval($item['post_id']); $all_views[$post_id] = intval($item['total_views']); } wp_cache_set($cache_key, $all_views, 'post_views', 3600); } return $all_views ?: array(); }
注:你之前直接SQL查询结果不一致,是因为Jetpack本地表按日期存储每日数据,必须通过
SUM(views)分组累加才能得到总浏览量,和stats_get_csv的返回逻辑匹配。
3. 调整超时与内存限制(解决批量获取超时问题)
如果批量获取时出现超时,在导出脚本开头添加以下设置:
// 延长PHP超时时间至5分钟 set_time_limit(300); // 调整内存限制(按需设置) ini_set('memory_limit', '256M');
为什么之前的方案无效?
- 直接SQL查询不一致:未处理Jetpack本地表的按日存储逻辑,没有累加每日数据;
- Transients缓存无效:仍在循环中逐个调用
stats_get_csv,首次获取时还是要发起多次请求; - 一次性获取超时:未调整PHP的超时和内存限制,导致大数量数据查询时中断。
内容的提问来源于stack exchange,提问作者Emiliano Developer
相关产品推荐
相关产品推荐

