Perl和SQLite—请求改进/优化多个SQL插入查询
我需要将JSON文件中的大量数据转换为SQLite数据库。我对INSERT查询做了一个简单的循环,但是查询花费了很多时间。我是一个业余爱好者,我一直在学习。我认为必须有一个更专业的解决方案Perl和SQLite—请求改进/优化多个SQL插入查询,sql,sqlite,perl,Sql,Sqlite,Perl,我需要将JSON文件中的大量数据转换为SQLite数据库。我对INSERT查询做了一个简单的循环,但是查询花费了很多时间。我是一个业余爱好者,我一直在学习。我认为必须有一个更专业的解决方案 use JSON::XS; use DBI; my $CCC = 'string'; # start connection to SQLite my $dbh = DBI->connect( "dbi:SQLite:dbname=aaaa.db", "", "", { Raise
use JSON::XS;
use DBI;
my $CCC = 'string';
# start connection to SQLite
my $dbh = DBI->connect(
"dbi:SQLite:dbname=aaaa.db", "", "", { RaiseError => 1 }, ) or die $DBI::errstr;
my $stmt = "CREATE TABLE IF NOT EXISTS $CCC (id INTEGER PRIMARY KEY AUTOINCREMENT, start INTEGER UNIQUE, open REAL NOT NULL, high REAL NOT NULL, low REAL NOT NULL, close REAL NOT NULL, vwp REAL NOT NULL, volume REAL NOT NULL, trades INTEGER NOT NULL)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
# Open file.json
open(my $fh, '<', file.json) or die "cannot open file";
{
local $/;
$data = <$fh>;
}
# Converting JSON format to Perl's variables
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
my $json = $coder->decode ($data);
# Loop. Im inserting every hash ({}) from file.json by INSERT sql statement
foreach (@{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
你知道更有效的方法吗?我认为你应该在foreach循环外准备语句(使用占位符),然后在循环内执行。准备工作通常只需进行一次
foreach (@{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
更新:将
unde
放置为Kjetil S建议的第一个参数。
我认为您应该在foreach循环外准备语句(使用占位符),然后在循环内执行。准备工作通常只需进行一次
foreach (@{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
更新:将
undef
作为Kjetil S.建议的第一个参数。
过去人们对这种事情进行过实验,例如我有一个解决这个问题的答案。它很有效!来自autocommit=0的查询在一分钟内结束,而其他两次尝试(不带此参数)运行了30分钟,但仍未完成。出于好奇,我将等待其他想法。你的循环和我的循环在性能上应该有区别吗?@J.Doe:ExecutingPRAGMA journal\u mode=MEMORY
应该会有很大的区别。过去人们已经在这方面做过实验,例如我有一个解决这个问题的答案。它是有效的!来自autocommit=0的查询在一分钟内结束,而其他两次尝试(不带此参数)运行了30分钟,但仍未完成。出于好奇,我将等待其他想法。你的循环和我的循环在性能上是否应该有差异?@J.Doe:ExecutingPRAGMA journal\u mode=MEMORY
应该有很大的区别。在execute
中,你可能应该用unde
替换'null'
(不带引号)。在execute
中,您可能应该将'null'
替换为unde
(不带引号)。
my $stmt = "INSERT INTO $CCC values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
my $sth = $dbh->prepare( $stmt );
foreach (@{$json}) {
$sth->execute(undef, $_->{T}, $_->{O}, $_->{H}, $_->{L}, $_->{C}, ($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4, $_->{V}, 1) or die $DBI::errstr;
}