我只是尝试使用带有pdo的LOAD DATA LOCL INFILE。没有为我做好准备。在这里我的功能
function connect($db_name,$db_host,$db_user,$db_pass)
{
try
{
$this->connect = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$this->connect->exec("LOAD DATA LOCAL INFILE 'http://localhost/testoo.csv'
INTO TABLE 'parsed'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
('name','link','price','brand','imageurl')");
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
现在没有任何反应。相同的查询适用于普通的mysql_query。这个问题有什么指针吗?
7年后Sammitch在这里说我原来的答案很严重。我甚至无法弄清楚我在谈论“fgetcsv()
资源使用问题”。 7年前,PHP可能缺少今天的一些IO流优化,但我愿意认为这是与PHP无关的资源限制。
Jay Dhameliya下面的回答很可能是你想要的方式。 LOAD DATA INFILE
应该尽可能快地将数据直接发送到mySQL。
为了完整起见,假设有一些东西阻止使用LOAD DATA INFILE
[就像最近发现的巨大安全漏洞]并且你想要有效地从文件中加载数据,你可能希望利用事务来批量IO和索引写入。例如:
$fname = 'myfile.csv';
if( ! $fh = fopen($myfile, 'r') ) {
throw new Exception("Could not open $fname for reading.");
}
$dbh = new PDO(...);
$dbh->beginTransaction();
$stmt = $dbh->prepare('INSERT INTO table VALUES (?,?,?,...)')
try {
while( $params = fgetcsv($fh) ) {
$stmt->execute($params);
}
} catch( \PDOException $e ) {
$dbh->rollBack();
throw $e;
}
$dbh->commit();
将所有内容分成一个事务仍然是LOAD DATA INFILE
如此之快的原因之一,并且可能是@ Benjamin建议使用扩展插入的一大部分。
或者:使用fgetcsv()
并以编程方式创建插入。
为避免fgetcsv()
的资源使用问题[因为它试图立即读取整个文件],您可以创建类似于下面的循环来读取/插入可管理的块。
<?php
$fname = 'myfile.csv';
$chunksize = 50;
if( ! $fh = fopen($myfile, 'r') ) {
throw new Exception("Could not open $fname for reading.");
}
$i=0;
$buffer = array()
while(!feof($fh)) {
$buffer[] = fgets($fh);
$i++;
if( ($i % $chunksize) == 0 ) {
commit_buffer($buffer);
//run inserts
$buffer = array(); //blank out the buffer.
}
}
//clean out remaining buffer entries.
if( count($buffer) ) { commit_buffer($buffer); }
function commit_buffer($buffer) {
foreach( $buffer as $line ) {
$fields = explode(',', $line);
//create inserts
}
//run inserts
$buffer = array(); //blank out the buffer.
}
这样,在任何给定时间只有$chunksize
线存储在存储器中。
您可能需要额外的代码来处理包含逗号和换行符的封装字符串,但如果您无法使LOAD DATA LOCAL INFILE
工作,我看不到其他选择。
在PDO连接选项中设置属性PDO::MYSQL_ATTR_LOCAL_INFILE
:
function connect($db_name,$db_host,$db_user,$db_pass)
{
try
{
$this->connect = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass,array(PDO::MYSQL_ATTR_LOCAL_INFILE => true));
$this->connect->exec("LOAD DATA LOCAL INFILE 'http://localhost/testoo.csv'
INTO TABLE 'parsed'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
('name','link','price','brand','imageurl')");
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
我有同样的问题。我的MySQL服务器有正确的本地infile conf,PHP/PDO
也有正确的PDO::MYSQL_ATTR_LOCAL_INFILE
conf。解决方案是(重新)安装php5-mysqlnd。
$> apt-get update
$> apt-get install php5-mysqlnd
......它工作了:)