[pgsql-jp: 25173] Re: INSERT文に関して
KAWAI,Takanori
GCD00051 @ nifty.ne.jp
2002年 3月 9日 (土) 11:39:36 JST
川合孝典です。
私としても杉田さんの書かれている通り、まずは実際にやって試して
見るのが一番だと思います。(人に聞くより確実にレスポンスがあるし)
----- Original Message -----
From: "Tadashi Kanbayashi" <Tadashi.Kanbayashi @ toppan.co.jp>
To: <pgsql-jp @ ml.postgresql.jp>
Sent: Friday, March 08, 2002 10:48 AM
Subject: [pgsql-jp: 25147] Re: INSERT文に関して
> 神林です。
(中略)
> PostgreSQLの場合も、prepareした後のSQL文の解析結果は、
> キャッシュされているんでしょうか。パフォーマンス的にもそうであれば
> 教えていただいた方法が最良かと思います。
#解析結果のキャッシュってOracleとかのイメージなんでしょうけれども
DBD::Pgのドキュメント(いくつかあるんですがPg.pmのPOD部分)に
あるよう、SQLの解析結果はキャッシュはされません。
<引用>
PostgreSQL does not have the concept of preparing
a statement. Hence the prepare method just stores
the statement after checking for place-holders.
No information about the statement is available
after preparing it.
</引用>
ただDBD::PgとしてはSQLステートメントそのものやプレースホルダに
関する情報は保持していますから、そのあたりがあとから効いてきます。
で、実際試してみましたが、当然というかCOPYコマンドがぶっちぎりの
最速です。特にデータが大量になればなるほど効いてくるでしょう。
変数を埋め込むと遅くなるのは当たり前(prepareも入りますけど、
それ以前にステートメントを展開するのにも時間が掛かりますしね)
また件数が多くなると複数ステートメントを1度に実行したほうが
プレースホルダを利用するよりも遅くなってしまいました。
CPUタイムからするとPostgreSQL本体のほうで時間が掛かって
いるようにも見えますが、さだかではありません。
#少なくともあまりいい手段だとも思えないし。
[環境]
TurboLinux6.0 Workstation PostgreSQL 7.1.3
Perl 5.00503 Pg 1.9.0
[実行結果]
1000件
COPY : 0 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
Embed: 2 wallclock secs ( 0.91 usr + 0.11 sys = 1.02 CPU)
Place: 1 wallclock secs ( 0.29 usr + 0.04 sys = 0.33 CPU)
Multi: 0 wallclock secs ( 0.02 usr + 0.00 sys = 0.02 CPU)
2000件
COPY : 0 wallclock secs ( 0.02 usr + 0.00 sys = 0.02 CPU)
Embed: 4 wallclock secs ( 1.78 usr + 0.33 sys = 2.11 CPU)
Place: 2 wallclock secs ( 0.54 usr + 0.15 sys = 0.69 CPU)
Multi: 2 wallclock secs ( 0.05 usr + 0.01 sys = 0.06 CPU)
10,000件
COPY : 0 wallclock secs ( 0.10 usr + 0.00 sys = 0.10 CPU)
Embed:19 wallclock secs ( 8.80 usr + 0.90 sys = 9.70 CPU)
Place:11 wallclock secs ( 2.45 usr + 0.62 sys = 3.07 CPU)
Multi:18 wallclock secs ( 0.24 usr + 0.07 sys = 0.31 CPU)
[実行したスクリプト]
use strict;
use Benchmark;
use DBI;
my @tb;
my $hDb = DBI->connect('dbi:Pg:dbname=gotdate', 'postgres', '',
{AutoCommit=>0, RaiseError=>1}) || die $DBI::errstr;
$hDb->do('DROP TABLE emp');
$hDb->do('CREATE TABLE emp (no integer, name varchar(80))');
my @aData = ([10, 'ABC']) x $ARGV[0];
my $sSQL = 'SELECT COUNT(*) FROM emp';
eval {
#1. COPY command
print "COPY:\n";
$hDb->do('DELETE FROM emp');
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
print scalar(localtime), "\n";
push(@tb, Benchmark->new);
{
my $raData;
$hDb->do('copy emp from stdin');
foreach $raData (@aData) {
$hDb->func(join("\t", @$raData). "\n", 'putline');
}
$hDb->func("\\.\n", 'putline');
$hDb->func('endcopy');
}
push(@tb, Benchmark->new);
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
#2. Embed
print "Embed:\n";
$hDb->do('DELETE FROM emp');
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
print scalar(localtime), "\n";
push(@tb, Benchmark->new);
{
my $raData;
foreach $raData (@aData) {
$hDb->do(
'INSERT INTO emp VALUES('.
join(',', map { "'$_'"} @$raData). ')');
}
$hDb->commit;
}
push(@tb, Benchmark->new);
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
#3. Placeholder
print "Placeholder:\n";
$hDb->do('DELETE FROM emp');
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
print scalar(localtime), "\n";
push(@tb, Benchmark->new);
{
my $raData;
my $hSt = $hDb->prepare('INSERT INTO emp VALUES(?, ?)');
foreach $raData (@aData) {
$hSt->execute(@$raData);
}
$hDb->commit;
}
push(@tb, Benchmark->new);
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
#4. Multi-Statement
print "Multi:\n";
$hDb->do('DELETE FROM emp');
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
print scalar(localtime), "\n";
push(@tb, Benchmark->new);
{
my @aSt = map {
'INSERT INTO emp VALUES('.
join(',', map { "'$_'"} @$_). ");\n";
} @aData;
$hDb->do("@aSt");
$hDb->commit;
}
push(@tb, Benchmark->new);
print "CNT:", $hDb->selectrow_array($sSQL), "\n";
};
die $@ if($@);
$hDb->disconnect;
print "COPY :",timestr(timediff($tb[1], $tb[0])),"\n";
print "Embed:",timestr(timediff($tb[3], $tb[2])),"\n";
print "Place:",timestr(timediff($tb[5], $tb[4])),"\n";
print "Multi:",timestr(timediff($tb[7], $tb[6])),"\n";
===================================================
川合 孝典 (Hippo2000)
DBI日本語メーリングリスト管理人、Kansai.pm所属
kwitknr @ cpan.org GCD00051 @ nifty.ne.jp
http://member.nifty.ne.jp/hippo2000
http://www.hippo2000.net/
「Perlを256倍使うための本 DBI編」 3/14発売
http://www.ascii.co.jp/books/detail/4-7561/4-7561-4058-0.html
===================================================
pgsql-jp メーリングリストの案内