生成包含大量数据的XML文件并避免内存上限

时间:2012-11-23 21:40:47

标签: php xml wordpress

我现在有一个Wordpress网站,里面有大约300k页面,还有一个内存为1GB的服务器。不幸的是,所有生成站点地图的插件都无法再处理它。我已经尝试了3种使用PHP(XMLWriter,SimpleXMLElement和DOMDocument)编写XML的不同方法,它们最终都会在大约30k页(xml节点)上加盖。

您认为我能做些什么来完成这项工作?在最糟糕的情况下,我考虑过设置多个cron作业,这些作业每天运行一次,每隔十分钟运行一次并继续打开/附加到文件中,只是添加到块中,但这显然不是最佳解决方案。我找到了一些声称可以在我的循环中清除内存的片段,但它也没有做到这一点。以下是该代码段的示例:

$xml = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
for ($i = 0 ; $i< 20; $i++) {
  $query = mysql_query(sprintf("SELECT ID, post_date FROM wp_posts WHERE post_status='publish' LIMIT %s,%s", $i*10000, 10000));
  while ($row = mysql_fetch_array($query)) {
    $xml .= '<url>';
    $xml .= '<loc>'.get_permalink($row['ID']).'</loc>';
    $xml .= '<lastmod>'.$row['post_date'].'</lastmod>';
    $xml .= '<changefreq>weekly</changefreq>';
    $xml .= '<priority>0.6</priority>';
    $xml .= '</url>';
  }
}
$xml .= '</urlset>';

$sxe = new SimpleXMLElement($xml);
$sxe->asXML("sitemap.xml");

1 个答案:

答案 0 :(得分:3)

为什么要一次抓取所有记录?

尝试每个请求获得10000行。并在每次迭代后清理内存。

如果您在cli模式下运行,旧版本的php不会释放内存,因此您可以尝试分叉http://php.net/manual/en/function.pcntl-fork.php

怎么做:

  1. 无需使用任何xml库,sprintf就可以了。
  2. 换入($ i = 0,$ i&lt; 5,$ i ++){}
  3. 查询看起来像LIMIT ($i*10000) 10000
  4. 代码示例:

    for ($i = 0 ; $i< 5 $i++) {
        ...
        $sth = $dbh->prepare('SELECT * FROM table_name LIMIT ? ?');
        $sth->execute(array($i*10000, 10000));
        ...
    }
    

    另一个代码示例:

        <?php
        $fileHandle = fopen("sitemap.xml", "w");
    
        fwrite($fileHandle,
            '<?xml version="1.0" encoding="UTF-8"?>' . 
            '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"' .
            ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' .
            ' xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9' .
            ' http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">'
        );
    
        for ($i = 0 ; $i< 20; $i++) {
            $query = mysql_query(sprintf("SELECT ID, post_date FROM wp_posts WHERE post_status='publish' LIMIT %s,%s", $i*10000, 10000));
            $xml = '';
            while ($row = mysql_fetch_array($query)) {
                $xml .= '<url>'.
                    '<loc>'.get_permalink($row['ID']).'</loc>' .
                    '<lastmod>'.$row['post_date'].'</lastmod>' .
                    '<changefreq>weekly</changefreq>' .
                    '<priority>0.6</priority>' .
                    '</url>';
            }
    
            fwrite($fileHandle, $xml);
        }
        fwrite($fileHandle, '</urlset>');
    
        fclose($fileHandle);
    
        echo PHP_EOL . 'memory used: '. memory_get_peak_usage() . PHP_EOL;