【发布时间】:2013-10-05 13:59:53
【问题描述】:
我的脚本存在问题,该脚本从 csv 文件导入条目并将它们作为 wordpress 自定义帖子插入(每一行都是一个帖子)... 最初,我在它自己的类中设置了导入功能,但几乎没有工作......从我收集的信息来看,问题是全局变量没有被缓存,每次我调用实例时都会消耗更多内存,直到进程内存不足并崩溃了...所以我删除了该类并设置了导入功能,如下面的代码所述。
通过此设置,我可以正常处理多达 17k 个帖子,但是如果我尝试导入比这更多的帖子,它就会退出而没有任何错误(我的 php 错误中没有报告错误log 或 wordpress debug.log 文件)
脚本成功插入 17k 个帖子,打印出回显信息,直到它在“剩余 XXX 项”处过早停止,并完成加载页面,此时不再输出……它永远不会进入决赛echo "Done!";声明...
这发生在 localhost 开发环境和托管开发服务器上。 我一直关注内存使用情况,在我的本地主机上它从未超过 60%(从 ~50% 开始),而且我没有看到表明内存泄漏的逐步内存攀升...
我也尝试过使用 ini_set('memory_limit', '64M');和 set_time_limit(0);
根据我读到的其他类似问题,
- 对于 SQL 20k 条目应该没什么大不了的
- wordpress 应该也能处理这个问题,如果服务器是 足够强大
我可以对下面的代码进行哪些优化/改进以使该脚本在这种规模上工作?
或者可能跳过 wordpress 的内置功能并使用 LOAD DATA INFILE 处理所有内容,正如 fancypants here 所提到的那样
我更愿意通过提供的 wordpress 功能处理数据。
csv 文件约为 1mb...
代码:
这些函数驻留在它们自己的文件中 - import.php
function fileupload_process() {
ini_set('memory_limit', '64M');
set_time_limit(0);
$uploadfiles = $_FILES['uploadfiles'];
if (is_array($uploadfiles)) {
foreach ($uploadfiles['name'] as $key => $value) {
// look only for uploaded files
if ($uploadfiles['error'][$key] == 0) {
$filetmp = $uploadfiles['tmp_name'][$key];
if (($handle = fopen($filetmp, "r")) !== FALSE) {
$flag = true;
$songs = explode("\n",file_get_contents($filetmp));
$count = count( $songs );
unset($songs);
echo "Total item count: " . $count . "<BR />";
// typical entry: If You Have To Ask,Red Hot Chili Peppers,0:03:37, Rock & Alternative,1991,on
// using a generous 1000 length - will lowering this actually impact performance in terms of memory allocation?
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// Skip the first entry in the csv containing colmn info
if($flag) {
$flag = false;
echo "<BR />";
$count--;
continue;
}
// insert the current post and relevant info into the database
$currently_processed = process_custom_post($data, $count);
$count--;
}
echo "Done!";
fclose($handle);
}
unlink($filetmp); // delete the temp csv file
}
}
}
} // END: file_upload_process()
function process_custom_post($song, $count) {
$track = (array_key_exists(0, $song) && $song[0] != "" ? $song[0] : 'N/A');
$artist = (array_key_exists(1, $song) && $song[1] != "" ? $song[1] : 'N/A');
$length = (array_key_exists(2, $song) && $song[2] != "" ? $song[2] : 'N/A');
$genre = (array_key_exists(3, $song) && $song[3] != "" ? $song[3] : 'N/A');
$year = (array_key_exists(4, $song) && $song[4] != "" ? $song[4] : 'N/A');
$month = (array_key_exists(5, $song) && $song[5] != "" ? $song[5] : 'N/A');
$playlist = (array_key_exists(6, $song) && $song[6] != "" ? $song[6] : '');
$custom_post = array();
$custom_post['post_type'] = 'songs';
$custom_post['post_status'] = 'publish';
$custom_post['post_title'] = $track;
echo "Importing " . $artist . " - " . $track . " <i> (" . $count ." items remaining)...</i><BR />";
$post_id = wp_insert_post( $custom_post );
$updated = update_post_meta($post_id, 'artist_name', $artist);
$updated = update_post_meta($post_id, 'song_length', $length);
$updated = update_post_meta($post_id, 'song_genre', $genre);
$updated = update_post_meta($post_id, 'song_year', $year);
$updated = update_post_meta($post_id, 'song_month', $month);
$updated = update_post_meta($post_id, 'sample_playlist', $playlist);
return true;
} // END: process_custom_post()
function import_page () {
//HTML for the import page + the file upload form
if (isset($_POST['uploadfile'])) {
fileupload_process();
}
}
import.php 包含在插件类之外的 wordpress 插件中
这里是关于我如何在导入页面上获取脚本的相关信息:
define( 'MY_PLUGIN_ROOT' , dirname(__FILE__) );
include_once( MY_PLUGIN_ROOT . 'import.php');
class my_plugin () {
function __construct() {
add_action( 'init', array( &$this, 'admin_menu_init' ) );
}
function admin_menu_init() {
if(is_admin()) {
//Add the necessary pages for the plugin
add_action('admin_menu', array(&$this, 'add_menu_items'));
}
}
function add_menu_items() {
add_submenu_page( 'edit.php?post_type=songs', 'Import Songs', 'Import Songs', 'manage_options', 'import-songs', 'import_page' );
}
}
任何想法、cmets 或建议将不胜感激。
【问题讨论】:
-
我能看到的唯一推荐是在 while 循环中获取您的计数,而不是读取整个文件然后将其分解以获取计数。此外,您似乎只是使用计数器来输出它以供人类阅读。每当我进行大量导入时,我只会在最后回显,可能只有几行,向屏幕输出 20k 行可能是另一个问题。
-
我把所有的echo语句都拿出来了,除了最后的echo 'Done!';,我省略了count文件爆炸并在循环中实现了……它仍然没有导入所有的帖子,停止在 ~17K ......但是,我现在收到 500 内部服务器错误,即使我的提供商的服务器日志文件完全没有任何错误?我将尝试在 localhost 上执行此操作,因为我有更多的监督可用,并希望我能看看我是否可以找到导致此问题的问题....
-
不走运,本地主机退出时没有像以前一样的错误...无论如何感谢您的建议
-
您是从本地/远程数据库获取原始帖子,还是 csv 文件是您发布数据的唯一来源。如果您可以访问数据库,只需将表转储到 sql 文件
-
不知道是不是第17k行附近的文件没有问题?
标签: php mysql wordpress performance csv