我在XML文件中有大约30K条记录,而且这个文件一直在更新。
我正在尝试插入并且如果存在则更新MySQL数据库。
这是我想要使用的代码,但运行速度非常慢,是否有人有任何提高其性能的想法?
// getting xml file
$dom = new DOMDocument();
$dom->load('products.xml');
// getting xml nodes using xpath
$xpath = new DOMXPath($dom);
$productid = $xpath->query('//NewDataSet/Product/ProductId');
$price = $xpath->query('//NewDataSet/Product/Price');
// Reading all nodes and if mach found in db update price, else insert as new record**
for($i=0;$i<$allNodes->length;$i++){
$testproductid = $productid->item($i)->nodeValue;
$testprice = $price->item($i)->nodeValue;
if(mysql_num_rows(mysql_query("Select productid from test where productid ='$testproductid'"))){
mysql_query("UPDATE test SET price = '$testprice' WHERE productid = '$testproductid'");
}else{
mysql_query("INSERT INTO test (price, productid) VALUES ('$testprice','$testproductid')");
}
}
答案 0 :(得分:0)
首先,我建议刷一些MySQL。第二关,通过使用您的主键
productid
字段,可以使用更高级的sql语句调用:
insert ... on duplicate key update ...
It's gonna halve your database lookups for the first part,因为您在插入/更新之前正在进行一次额外的测试。
其次,XML可能不是您的跨平台文件的最佳解决方案。你使用这个的任何特殊原因?
答案 1 :(得分:0)
为什么两个查询哪个就足够了?
$sql = "INSERT INTO test (price, productid) " .
"VALUES ('$testprice','$testproductid') " .
"ON DUPLICATE KEY UPDATE";
if(!$query = mysql_query($sql))
trigger_error(mysql_error());
您也可以尝试使用SimpleXML来代替DOMDocument,但是我可以通过Google获得任何记录的速度差异。
答案 2 :(得分:0)
首先,这一行可能导致不良行为:
if(mysql_num_rows(mysql_query("Select productid from test where productid ='$testproductid'")))
如果mysql_query()失败会怎么样?做一些类似的事情:
$res = mysql_query("Select productid from test where productid ='$testproductid'");
if ($res) {
... CODE HERE ...
}
productid 是一个索引吗?此外,您可以将查询表示为:
Select productid from test where productid ='$testproductid' LIMIT 1
在这种情况下,MySQL不会查找更多记录。此外,尝试在单个INSERT语句中插入多个记录。见:
http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
查看REPLACE命令。这将取代SELECT / UPDATE / INSERT条件,但它可能不会对性能有很大的改进。
答案 3 :(得分:0)
另外,如果您不介意特定于mysql,则REPLACE会在一个语句中执行INSERT / UPDATE。或者您可以执行INSERT ... ON DUPLICATE KEY UPDATE。特别是,这取消了“if(mysql_num_rows(mysql_query(”select productid from test where productid ='$ testproductid'))))“。
答案 4 :(得分:0)
此外,如果您不介意特定于mysql,则REPLACE
在一个语句中执行INSERT
/ UPDATE
。或者你可以做INSERT ... ON DUPLICATE KEY UPDATE
。特别是,这取消了if(mysql_num_rows(mysql_query("Select productid from test where productid ='$testproductid'")))
。
答案 5 :(得分:0)
通过块加载大文件的脚本 它将加载xml文件,一次读取给定数量的条目,然后将它们加载到数据库中。
$lot =5000;
$tempFiledir = '.';
$tempFile = 'temp.xml';
$table = 'mytable';
$db_username= 'root';
$db_password = 'mysql';
// count element
print( " Computing items...");
$xml_reader = new XMLReader;
$xml_reader->open($xml_file);
while ($xml_reader->read() && $xml_reader->name != $node_name);
$totalItems =0;
while ($xml_reader->name == $node_name) {
$xml_reader->next($node_name);
$totalItems++;
}
$xml_reader->close();
print( "\r $totalItems items found. ");
//Truncat the table to load into
$xmlload_cmd = sprintf ("$mysql_exe -u%s -p%s $database_temp -e \"TRUNCATE TABLE `%s`;\" ", $db_username, $db_password, $table);
system($xmlload_cmd);
// move the pointer to the first item
$xml_reader = new XMLReader;
$xml_reader->open($xml_file);
while ($xml_reader->read() && $xml_reader->name != $node_name);
// load by chunks
$index = 0;
while ($xml_reader->name == $node_name){
$tempFileXMLOutput = fopen( "$tempFiledir\\$tempFile", "w") or die("Unable to open file!");
fwrite($tempFileXMLOutput,'<?xml version="1.0"?>');
$index0=$index;
do {
// remove self closign tags from the rendred xml output and store it in the temp file
$data = preg_replace('/\<(\w+)\s*\/\s*\>/i', '<$1></$1>', $xml_reader->readOuterXML());
fwrite($tempFileXMLOutput, "\n\t$data");
// move the pointer to the next item
$xml_reader->next($node_name);
$index++;
}
while ($xml_reader->name == $node_name && ($index % $lot != 0) );
// close the temp file
fclose($tempFileXMLOutput);
echo sprintf("\r Processing items from %6s to %6s [%3.0f%%]", $index0, $index, $index/$totalItems*100);
// run the LOAD XML comand on the temp xml file
$load_cmd = sprintf("LOAD XML LOCAL INFILE '%s' INTO TABLE `%s` ROWS IDENTIFIED BY '<Data>'", addslashes("$tempFiledir\\$tempFile"), $table);
$xmlload_cmd = sprintf ("$mysql_exe -u%s -p%s $database_temp -e \"$load_cmd\" ", $db_username, $db_password);
system($xmlload_cmd);
// remove the temp file
@unlink ( "$tempFiledir\\$tempFile");
}
$xml_reader->close();