我正在尝试将一个庞大的xml文件解析到我的MySQL数据库中。该文件是4.7克。 我知道,它疯了。
数据来自:http://www.discogs.com/data/(最新专辑xml是700mb压缩,4.7gb解压缩)
我可以使用java或php来解析和更新数据库。我认为java是更明智的想法。
我需要找到一种方法来解析xml而不填充我的4gb ram,并将其加载到db中。
这样做最聪明的方法是什么?我听说过SAX解析器,我在想正确的方向吗?
目前,我不关心从这些网址下载图片,我只想要数据库中的数据。我还没有设计这些表,但我现在对xml方面更感兴趣。
我使用php的fread()来打开文件的前1000个叮咬,所以至少我可以看到它的样子,这里是文件中第一张专辑结构的样本:
<releases>
<release id="1" status="Accepted">
<images>
<image height="600" type="primary" uri="http://s.dsimg.com/image/R-1-1193812031.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812031.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812053.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812053.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812072.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812072.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812091.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812091.jpeg" width="600" />
</images>
<artists>
<artist>
<name>Persuader, The</name>
</artist>
</artists>
<title>Stockholm</title>
<labels>
<label catno="SK032" name="Svek" />
</labels>
<formats>
<format name="Vinyl" qty="2">
<descriptions>
<description>12"</description>
</descriptions>
</format>
</formats>
<genres>
<genre>Electronic</genre>
</genres>
<styles>
<style>Deep House</style>
</styles>
<country>Sweden</country>
<released>1999-03-00</released>
<notes>Recorded at the Globe studio in Stockholm. The titles are the names of Stockholm's districts.</notes>
<master_id>5427</master_id>
<tracklist>
<track>
<position>A</position>
<title>Östermalm</title>
<duration>4:45</duration>
</track>
<track>
<position>B1</position>
<title>Vasastaden</title>
<duration>6:11</duration>
</track>
<track>
<position>B2</position>
<title>Kungsholmen</title>
<duration>2:49</duration>
</track>
<track>
<position>C1</position>
<title>Södermalm</title>
<duration>5:38</duration>
</track>
<track>
<position>C2</position>
<title>Norrmalm</title>
<duration>4:52</duration>
</track>
<track>
<position>D</position>
<title>Gamla Stan</title>
<duration>5:16</duration>
</track>
</tracklist>
</release>
感谢。
答案 0 :(得分:2)
你显然需要一个流式API而不是一个DOM,它需要将整个文档保存在内存中。 Java支持SAX和Stax。我自己从未使用过Stax,但听说它比SAX更容易使用,但仍然有效。
确保将工作拆分为多个事务:数据库将无法在单个事务中支持尽可能多的插入语句。
答案 1 :(得分:1)
如果我在哪里使用PHP解析它,我会分两步完成:
<release>
点击文件并使该minifile成为有效的XML。如果速度不重要,那么PHP实际上会更好,因为在PHP中解析文本/ XML很容易。
答案 2 :(得分:1)
我前段时间遇到类似的问题。这里是导入大约28MB文件的脚本巫婆的一部分,而不是将整个数据读入内存。它可能应该工作:)。它由XML节点读取,在内存中只保留XML的一小部分。脚本将需要很少的修改来满足您的需求。
$reader = new XMLReader();
$reader->open(<path_to_large_xml_file>);
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "Table") {
$node = $reader->expand();
$dom = new DomDocument();
$n = $dom->importNode($node,true);
$dom->appendChild($n);
$sxe = simplexml_import_dom($n);
$Data = array();
$DataColumns = array();
foreach ($columns as $key => $column)
{
if (in_array($key,$DateColumns))
{
$DateArray = explode('/',substr(trim($sxe->$column),0,10));
$ValueColumn = date('Y-m-d H:i:s',mktime(0,0,0,$DateArray[1],$DateArray[0],$DateArray[2]));
$Data[] = '\''.$ValueColumn.'\'';
$DataColumns[] = $key;
if ($SplitDateInsert == 'enabled')
{
$Data[] = '\''.$DateArray[2].'\'';
$Data[] = '\''.$DateArray[1].'\'';
$Data[] = '\''.$DateArray[0].'\'';
$DataColumns[] = $key.'_year';
$DataColumns[] = $key.'_month';
$DataColumns[] = $key.'_day';
}
} else {
$ValueColumn = addslashes(trim($sxe->$column));
$Data[] = '\''.$ValueColumn.'\'';
$DataColumns[] = $key;
}
}
$SQL = "INSERT INTO {$tableName} (".implode(',',$DataColumns).") VALUES (".implode(',',$Data).")";
$db->query($SQL);
} // END IF table
}
}
答案 3 :(得分:0)
假设MySQL在这方面具有类似Oracle的功能,为什么不让DB处理解析呢?在oracle中,你可以只注册XMLSchema,创建一个结构化的XMLType表(可能比clob更有用),然后插入文件。
从来没有将它用于任何那么大的东西,但是我不明白为什么它不应该工作,而且只需几行代码即可完成。您只需要具有MySQL经验的人来讲述详细信息的工作原理。
答案 4 :(得分:0)
我建议在Java上使用Stax。或者,更简单的是,StaxMate为访问增加了更多便利。
但是你究竟需要用XML做什么?要在数据库中流式传输它,有一些方法可以将BLOB作为流处理(虽然mySQL JDBC驱动程序因怪癖而臭名昭着)所以这应该是可行的。
答案 5 :(得分:0)
4.7 GB不是疯了,只是轻微的。如果您使用64位Java,则扩展VTD-XML应该是最有效且易于使用的选项。
答案 6 :(得分:0)
您还没有说过要对XML进行哪些处理。您可以考虑使用Saxon的流模式XSLT(它需要Saxon-EE产品,这需要花钱) - 如果处理本质上是一个“突发模式流”练习依次处理每个“释放”元素,那么它应该'太难了。当然,您也可以使用低级SAX或StaX解析,但这几乎肯定需要开发和调试更多的代码。