DBD::SQLite 插入多行的最快方法
DBD::SQLite fastest way to insert multiple rows
我尝试了 3 种不同的方法来将多行(超过 500 行)插入 SQLite table。与直觉相反,下面的方法 3 是最快的。我原以为方法 2 是最快的,因为它使用 "prepared" 语句句柄。但是我的第三种方法——一次插入 500 行(500 显然是 SQLite 中允许的最大值)——要快得多。
我错过了什么吗?我应该继续使用 500 方法,还是有其他方法?
注意:下面的代码不是我的实际代码,我只是为了示例目的而写在这里,并没有经过测试。
use strict;
use warnings;
use DBI;
my $dsn = "DBI:SQLite:dbname=db";
my $dbh = DBI->connect($dsn,"","");
open my $data_file,"<","data.txt"; # 3 integer fields per line
APPROACH_1:
while (<$data_file>) {
my @fields = split "\t";
my $insert = join ",", @fields;
$dbh->do("insert into table values ($insert)";
}
APPROACH_2:
my $sql = "insert into table values (?,?,?)";
my $sth = $dbh->prepare($sql);
while (<$data_file>) {
my @fields = split "\t";
$sth->execute(@fields);
}
APPROACH_3:
my @inserts;
while (<$data_file>) {
my @fields = split "\t";
my $insert = '('.join(",",@fields).')';
push @inserts, $insert;
if (@inserts == 500) {
my $insert_500 = join ",", @inserts;
$dbh->do("insert into table values $insert_500";
undef @inserts;
}
}
# insert leftovers
请参阅下面的示例,其中自动提交设置为 0
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect("dbi:SQLite:dbname=pedro.lite","","",
{PrintError => 1, AutoCommit => 0}) or die "Can't connect";
my $sth = $dbh->prepare(q{INSERT INTO purchases VALUES(?,?,?,?)})
or die $dbh->errstr;
while (<DATA>) {
chomp;
$sth->execute( split /\|/ );
}
$dbh->commit() or die $dbh->errstr;
__DATA__
Pedro|groceries|apple|1.42
Nitin|tobacco|cigarettes|15.00
Susie|groceries|cereal|5.50
Susie|groceries|milk|4.75
Susie|tobacco|cigarettes|15.00
Susie|fuel|gasoline|44.90
Pedro|fuel|propane|9.60
这将禁用提交,直到插入所有记录。实际上,如果有很多插入,您可能不想等待提交 - 可能每 5000 次插入或您认为最好的任何时间。通过不提交,如果出现错误或计算机关闭,那么您将只会创建上次提交时的记录数 - 一个困难的情况。
我尝试了 3 种不同的方法来将多行(超过 500 行)插入 SQLite table。与直觉相反,下面的方法 3 是最快的。我原以为方法 2 是最快的,因为它使用 "prepared" 语句句柄。但是我的第三种方法——一次插入 500 行(500 显然是 SQLite 中允许的最大值)——要快得多。
我错过了什么吗?我应该继续使用 500 方法,还是有其他方法?
注意:下面的代码不是我的实际代码,我只是为了示例目的而写在这里,并没有经过测试。
use strict;
use warnings;
use DBI;
my $dsn = "DBI:SQLite:dbname=db";
my $dbh = DBI->connect($dsn,"","");
open my $data_file,"<","data.txt"; # 3 integer fields per line
APPROACH_1:
while (<$data_file>) {
my @fields = split "\t";
my $insert = join ",", @fields;
$dbh->do("insert into table values ($insert)";
}
APPROACH_2:
my $sql = "insert into table values (?,?,?)";
my $sth = $dbh->prepare($sql);
while (<$data_file>) {
my @fields = split "\t";
$sth->execute(@fields);
}
APPROACH_3:
my @inserts;
while (<$data_file>) {
my @fields = split "\t";
my $insert = '('.join(",",@fields).')';
push @inserts, $insert;
if (@inserts == 500) {
my $insert_500 = join ",", @inserts;
$dbh->do("insert into table values $insert_500";
undef @inserts;
}
}
# insert leftovers
请参阅下面的示例,其中自动提交设置为 0
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect("dbi:SQLite:dbname=pedro.lite","","",
{PrintError => 1, AutoCommit => 0}) or die "Can't connect";
my $sth = $dbh->prepare(q{INSERT INTO purchases VALUES(?,?,?,?)})
or die $dbh->errstr;
while (<DATA>) {
chomp;
$sth->execute( split /\|/ );
}
$dbh->commit() or die $dbh->errstr;
__DATA__
Pedro|groceries|apple|1.42
Nitin|tobacco|cigarettes|15.00
Susie|groceries|cereal|5.50
Susie|groceries|milk|4.75
Susie|tobacco|cigarettes|15.00
Susie|fuel|gasoline|44.90
Pedro|fuel|propane|9.60
这将禁用提交,直到插入所有记录。实际上,如果有很多插入,您可能不想等待提交 - 可能每 5000 次插入或您认为最好的任何时间。通过不提交,如果出现错误或计算机关闭,那么您将只会创建上次提交时的记录数 - 一个困难的情况。