我已经制作了这个脚本,我运行了一个WP_Query(),它可以获得2,000条记录并且正在增长。我希望能够将这些结果写入CSV文件。当posts_per_page设置为300或更少的记录时,我有这个工作。如何优化csv脚本的wp_query?
如果我改变posts_per_page为-1,然后我得到这个错误:
Fatal error: Allowed memory size of 134217728 bytes exhausted
我想知道,如果有,我可以在同一时间在同一时间发送300条记录到CSV文件,直到办法没有更多,然后触发文件下载?
或者也许可以将每行都流到CSV文件?在做fopencsv时管理内存的最佳方式是什么?
这是我现在有:
$export_query = array(
'post_type' => 'videorepot',
'posts_per_page' => -1,
'status' => 'published',
'meta_query' => array(
array(
'key' => 'agree',
'value' => 1,
'compare' => '=',
),
array(
'key' => 'opt-in',
'value' => 1,
'compare' => '=',
),
array(
'key' => 'status',
'value' => 'Video Ready',
'compare' => '=',
),
)
);
// Posts query
$wp_query = new WP_Query($export_query);
if ($wp_query->have_posts()) :
$list = array('Email,Photo1,Photo2,Photo3,VideoURL');
while ($wp_query->have_posts()) : $wp_query->the_post();
$postID = get_the_ID();
$user_email = get_post_meta($postID, 'user_email', true);
$photo1 = get_post_meta($postID, 'photo1', true);
$photo2 = get_post_meta($postID, 'photo2', true);
$photo3 = get_post_meta($postID, 'photo3', true);
$videourl = get_post_meta($postID, 'video_file', true);
$list[] = $user_email.','.$photo1.','.$photo2.','.$photo3.','.$videourl;
endwhile;
endif;
// Output file stream
$output_filename = 'export_' . strftime('%Y-%m-%d') . '.csv';
$output_handle = @fopen($output_filename, 'w');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename=' . $output_filename);
header('Expires: 0');
header('Pragma: public');
foreach ($list as $line) {
// Add row to file
fputcsv($output_handle, explode(',', $line), ',', '"');
}
// Close output file stream
fclose($output_handle);
// We're done!
exit;
更新#1 对于一些测试我删除写入资料转移到CSV文件中的脚本的一部分,所以我发现它真的我在这里查询的东西让它变得疯狂。我的自定义文章类型中可能有3000条记录。为什么这会让我的查询耗尽内存?
更新#2
,我决定走了不同的路线,因为我使用wp_query时仍然遇到内存问题。所以,我写了我的mySQL查询 - 你知道我从其他例子入侵它。这个查询运行得非常快,所以我想我会有更好的运气。
我有一个新的问题,因为这与meta_key/meta_values有关。目前,我在查询中使用SELECT *,但我不想选择所有内容。我只需要数据库中的大约5个字段。我想要的这些字段中的一些是meta_key/meta_value。有没有一种方法可以指定这些meta_keys,所以当我导出表格时,我只能得到5列结果?
我的查询看起来像现在这样:
$values = mysql_query("SELECT * FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1
AND ((post_date >= '2014-11-03 00:00:00' AND post_date <= '2014-12-31 23:59:59'))
AND wp_posts.post_type = 'videorepot'
AND (wp_posts.post_status = 'publish')
AND ((wp_postmeta.meta_key = 'agree' AND CAST(wp_postmeta.meta_value AS CHAR) = '1')
AND (mt1.meta_key = 'opt-in' AND CAST(mt1.meta_value AS CHAR) = '1')
AND (mt2.meta_key = 'status' AND CAST(mt2.meta_value AS CHAR) = 'Video Ready'))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0,20");
现在我设置的限制20,但我已经设置为0,9999极限测试,它的运行速度非常快,phpMyAdmin的。上面的查询给我约1282个结果,当我没有设置限制。
更新#3
我已经发布了一个解决方案,我的答案。感谢您的帮助David。
增加php内存...或者添加后期元来表示你已经下载并设置最大结果为200左右(不包括下载) – David 2014-12-11 00:59:00
我宁愿不只是增加PHP内存。我有兴趣学习在这种情况下正确的PHP技术来管理内存。我会暂时尝试这个。另外根据这个错误,我可以使用134 MB的内存,我认为这是相当高的。 事情是我想每次点击一个链接时导出完整的数据库,所以没有必要将项目设置为正在下载。尽管如此,感谢您的评论。 – Robbiegod 2014-12-11 02:34:05
是真实的,但你没有134 MB与...一起工作,但取消了你的循环后使用wp查询,而不是foreach(foreach再次创建另一个副本,所以你实际上有3个副本),然后取消设置$ list数组,当你循环它。 – David 2014-12-11 09:26:19