Php PDO和加载数据本地填充不工作
我只是尝试使用加载数据LOCL INFILE和pdo。不适合我。这是我的职责Php PDO和加载数据本地填充不工作,php,mysql,pdo,Php,Mysql,Pdo,我只是尝试使用加载数据LOCL INFILE和pdo。不适合我。这是我的职责 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
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\u查询。对这个问题有什么建议吗 2019年编辑
7年后,桑米奇在这里说,我最初的答案是粗俗的。我甚至搞不懂我到底在说什么“fgetcsv()
资源使用问题”。7年前的PHP可能缺少今天的一些IO流优化,但我愿意承认这是与PHP无关的资源约束
Jay Dhameliya下面的答案很可能就是您想要的方式。加载数据填充
应该尽可能快地将数据直接写入mySQL
为了完整性起见,假设存在阻止使用LOAD DATA infle
[如最近发现的巨大安全漏洞]的因素,并且您希望有效地从文件加载数据,那么您可能希望利用事务来批处理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();
将所有内容批处理到单个事务中仍然是使用加载数据填充
速度如此之快的部分原因,并且可能是@Benjamin建议使用扩展插入的一个重要部分
原始总答案
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.
}
在PDO连接选项中设置属性PDO::MYSQL\u ATTR\u LOCAL\u infle
:
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服务器有正确的本地infle配置,PHP/PDO
也有正确的PDO::MySQL\u ATTR\u local\u infle
conf。
解决方案是(重新)安装php5 mysqlnd。
$> apt-get update
$> apt-get install php5-mysqlnd
…成功了:)您收到错误消息了吗?您是否打开了错误报告功能?谢谢您,现在已捕获错误!“PDO::exec()[PDO.exec]:加载数据本地填充禁止”web服务器中的文件不是我定义的本地文件。。。它真的适用于旧版扩展吗?如果这是一次性的,那么就用php。。。只需从CLI客户端运行查询。。。完成和完成。:-)已经试过1次了。我的问题是,我有像80mb或更多的大文件,所以fgetcsv()是一种缓慢的方式,因为它将首先尝试将所有80mb加载到RAM中。Double或者用于加载X行,创建/运行插入,重复直到EOF。这仍然是一种减慢速度的方法。我必须定期导入3.000.000+行的CSV。我第一次尝试foreach循环和fgets()
需要一整晚的时间,而LOAD DATA LOCAL
可以在几分钟内完成任务。@GielBerkers“仍将”和“将”==您的推测。我想知道,如果不是完全相同的事情,mySQL客户机库会对文件做什么。此外,问题是关于加载数据根本不起作用的事实。@Sammitch如果您对此进行基准测试,您可能会对结果感到惊讶,这就是我在上面的链接中所做的!扩展插入总是要快得多。我确实在每种情况下都使用了事务和非模拟的预处理语句!这是唯一对我们有效的解决方案。感谢您的最佳回答,因为重点是使用实际的PDO。我的猜测是,大多数用户在设置时都会遇到问题,因为他们忘记了允许自动递增字段。。。在Jays的正确示例中,如果有一个自动递增字段(很可能),让我们假设call Table_ID,那么您应该在字段entries之后添加“SET Table_ID=NULL”;我还建议结合上述内容阅读此答案,以帮助理解必要的设置:非常感谢:)这确实是最好的解决方案。解决了我的问题。