使用PHP的大量SQLite插入

使用PHP的大量SQLite插入,php,sqlite,pdo,Php,Sqlite,Pdo,我尝试使用PHP PDO将大约14000行逗号分隔的值插入到sqlite表中,如下所示: <?php // create a PDO object $dbh = new PDO('sqlite:mydb.sdb'); $lines = file('/csv/file.txt'); // import lines as array foreach ($lines as $line) { $line_array = (','$line); // create an array of

我尝试使用PHP PDO将大约14000行逗号分隔的值插入到sqlite表中,如下所示:

<?php
// create a PDO object
$dbh = new PDO('sqlite:mydb.sdb');

$lines = file('/csv/file.txt'); // import lines as array
foreach ($lines as $line) {
    $line_array = (','$line); // create an array of comma-separated values in each line
    $values = '';
    foreach ($line_array as $l) {
        $values .= "'$l', ";
    }
    substr($values,-2,0); // get rid of the last comma and whitespace
    $query = "insert into sqlite_table values ($values)"; // plug the value into a query statement
    $dbh->query($query); // run the query
}

?>
来自:

事务速度受磁盘驱动器速度限制,因为(默认情况下) SQLite实际上会等到数据 真正安全地存储在磁盘上 在事务处理之前显示 完成那样的话,如果你突然 断电或者如果操作系统崩溃,您的 数据仍然是安全的。有关详细信息,请阅读 关于SQLite中的原子提交。。 [……]

另一个选项是运行PRAGMA synchronous=OFF。此命令将 使SQLite不等待数据传输 到达磁盘表面,这将 使写入操作看起来像是 快得多。但是如果你失去了权力 在交易的中间,你的 数据库文件可能已损坏

我想说最后一段是你需要的


EDIT:对此没有把握,但我相信使用sqlite\u unbuffered\u query()应该可以做到这一点。

通过在单个事务中包装插入,您将看到良好的性能提升。如果不这样做,SQLite会将每个插入视为自己的事务

<?php
// create a PDO object
$dbh = new PDO('sqlite:mydb.sdb');

// Start transaction
$dbh->beginTransaction();
$lines = file('/csv/file.txt'); // import lines as array
foreach ($lines as $line) {
    $line_array = (','$line); // create an array of comma-separated values in each line
    $values = '';
    foreach ($line_array as $l) {
        $values .= "'$l', ";
    }
    substr($values,-2,0); // get rid of the last comma and whitespace
    $query = "insert into sqlite_table values ($values)"; // plug the value into a query statement
    $dbh->query($query); // run the query
}
// commit transaction
$dbh->commit();

?>

在循环之前启动事务,并在循环之后提交它

现在代码的工作方式是,每次插入时它都会启动一个事务。如果您想提高速度,请使用prepare/fetch,这样SQL引擎就不必每次都解析文本字符串

$name = $age = '';
$insert_stmt = $db->prepare("insert into table (name, age) values (:name, :age)");
$insert_stmt->bindValue(':name', $name);
$insert_stmt->bindValue(':age', $age);

// do your loop here, like fgetcsv
while (get the data) {
list($name, $age) = split(',', $string);
$insert_stmt->execute();
}
在循环之外进行绑定是违反直觉的,但这也是该方法如此快速的原因之一,基本上是说“使用这些变量中的数据执行这个预编译的查询”。因此,它甚至不需要在内部移动数据。并且您希望避免重新解析查询,这是一个问题,如果您使用类似“insert into table(name)values(“$name”)”的内容,则每个查询都会将整个文本字符串发送到要重新解析的数据库


还有一件事可以加快它的速度——在事务中包装整个循环,然后在循环完成后提交事务。

这对我来说非常有效。我惊讶于它能如此快速地导入所有东西。谢谢。谢谢,你为我节省了很多时间!:)要获得更快的速度,请将语句准备与事务结合使用。在可能影响实际查询的值的情况下,如有意外的引号,也会使事情变得更安全。是否有一些条件使其工作?它似乎还没有结束是的,它很快,但它不会做你想要的。您需要在循环中进行绑定,您的代码将反复插入相同的值。