create table speedtest ( id integer, name varchar2(16), aod date, curr1 varchar2(6), price1 number, curr2 varchar2(6), price2 number ); #### #!/usr/local/bin/perl use strict; use warnings; use feature qw/say/; use Data::Dumper; use Time::HiRes qw/gettimeofday tv_interval/; use DBI; #-------------------------------------------------------- sub rowcnt { my $dbh = shift; my $rowcnt = $dbh->selectrow_array('select count(*) from speedtest'); return $rowcnt; } #-------------------------------------------------------- sub gencurr { my @set = 'A' .. 'F'; return join '' => map $set[rand @set], 1 .. 3; } #-------------------------------------------------------- sub genstr { my $len = shift; return sprintf("%08X", rand(0x7fffffff)); } #-------------------------------------------------------- sub gennum { return sprintf("%08d", rand(0x7fffffff)); } #-------------------------------------------------------- sub gendate { # 0 1 2 3 4 5 6 7 8 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(rand(0xffffffff)); return sprintf("%04d-%02d-%02d", $year+1900, $mon+1, $mday); } #-------------------------------------------------------- sub genreal { return sprintf("%10.6f", rand(0xffffffff)); } #-------------------------------------------------------- sub gendata { my $count = shift; my $d; for(my $i=0; $i<$count; ++$i) { $d->{$i}->{id} = gennum(); $d->{$i}->{name} = genstr(); $d->{$i}->{aod} = gendate(); $d->{$i}->{curr1} = gencurr(); $d->{$i}->{price1} = genreal(); $d->{$i}->{name} = genstr(); $d->{$i}->{curr2} = gencurr(); $d->{$i}->{price2} = genreal(); } return $d; } #-------------------------------------------------------- sub testins1 { my $dbh = shift; my $data = shift; say 'positional bind_param and execute by row'; my $isql = q{ insert /*+ append */ into speedtest (id, name, aod, curr1, price1, curr2, price2) values (?, ?, ?, ?, ?, ?, ?) }; my $isth = $dbh->prepare($isql); for my $i (sort keys %$data) { $isth->bind_param(1, $data->{$i}->{id}); $isth->bind_param(2, $data->{$i}->{name}); $isth->bind_param(3, $data->{$i}->{aod}); $isth->bind_param(4, $data->{$i}->{curr1}); $isth->bind_param(5, $data->{$i}->{price1}); $isth->bind_param(6, $data->{$i}->{curr2}); $isth->bind_param(7, $data->{$i}->{price2}); $isth->execute; } $isth->finish; $dbh->commit; } #-------------------------------------------------------- sub testins2 { my $dbh = shift; my $data = shift; say 'positional execute and execute by row'; my $isql = q{ insert /*+ append */ into speedtest (id, name, aod, curr1, price1, curr2, price2) values (?, ?, ?, ?, ?, ?, ?) }; my $isth = $dbh->prepare($isql); my @fields = qw/id name aod curr1 price1 curr2 price2/; for my $i (sort keys %$data) { $isth->execute(@{$data->{$i}}{@fields}); } $isth->finish; $dbh->commit; } #-------------------------------------------------------- sub testins3 { my $dbh = shift; my $data = shift; say 'positional execute array'; my $isql = q{ insert /*+ append */ into speedtest (id, name, aod, curr1, price1, curr2, price2) values (?, ?, ?, ?, ?, ?, ?) }; my $isth = $dbh->prepare($isql); my $id = [map { $data->{$_}->{id} } sort keys %$data]; my $name = [map { $data->{$_}->{name} } sort keys %$data]; my $aod = [map { $data->{$_}->{aod} } sort keys %$data]; my $curr1 = [map { $data->{$_}->{curr1} } sort keys %$data]; my $price1 = [map { $data->{$_}->{price1} } sort keys %$data]; my $curr2 = [map { $data->{$_}->{curr2} } sort keys %$data]; my $price2 = [map { $data->{$_}->{price2} } sort keys %$data]; my $t0 = [gettimeofday]; my $rv = $isth->execute_array({ ArrayTupleStatus => \my @tuple_status }, $id, $name, $aod, $curr1, $price1, $curr2, $price2); my $elapsed = tv_interval($t0, [gettimeofday]); say "\texecute_array takes $elapsed sec, $rv rows"; my @err = grep {$_ != -1} @tuple_status; say "\terr: @err"; $isth->finish; $dbh->commit; } #-------------------------------------------------------- sub testins4 { my $dbh = shift; my $data = shift; say 'bind_param by name and execute by row'; my $isql = q{ insert /*+ append */ into speedtest (id, name, aod, curr1, price1, curr2, price2) values (:id, :name, :aod, :curr1, :price1, :curr2, :price2) }; my $isth = $dbh->prepare($isql); for my $i (sort keys %$data) { $isth->bind_param(':id', $data->{$i}->{id}); $isth->bind_param(':name', $data->{$i}->{name}); $isth->bind_param(':aod', $data->{$i}->{aod}); $isth->bind_param(':curr1', $data->{$i}->{curr1}); $isth->bind_param(':price1', $data->{$i}->{price1}); $isth->bind_param(':curr2', $data->{$i}->{curr2}); $isth->bind_param(':price2', $data->{$i}->{price2}); $isth->execute; } $isth->finish; $dbh->commit; } #======================================================== $Data::Dumper::Sortkeys = 1; my $dbname = '???'; my $user = '???'; my $passwd = '???'; my $count = $ARGV[0] // 1; my $verbose = 0; $| = 1; my $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd, { AutoCommit => 0, RaiseError => 1, RowCacheSize => 10000, ora_array_chunk_size => 100000, #ora_check_sql => 0, #ora_verbose => 0xff, #ora_oci_success_warn => 1, } ); print 'DBI version: ', $DBI::VERSION, "\n"; print 'DBD version: ', $DBD::Oracle::VERSION, "\n"; $dbh->do("alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'"); $dbh->do("alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF'"); say "RowCacheSize: ", $dbh->{RowCacheSize}; my $data = gendata($count); say Dumper($data) if $verbose; my ($t0, $elapsed); $dbh->do('truncate table speedtest') or die "SPEEDTEST truncate failed"; $t0 = [gettimeofday]; testins1($dbh, $data); $elapsed = tv_interval($t0, [gettimeofday]); say "1 Elapsed: $elapsed sec " . rowcnt($dbh) . " rows"; $dbh->do('truncate table speedtest') or die "SPEEDTEST truncate failed"; $t0 = [gettimeofday]; testins2($dbh, $data); $elapsed = tv_interval($t0, [gettimeofday]); say "2 Elapsed: $elapsed sec " . rowcnt($dbh) . " rows"; $dbh->do('truncate table speedtest') or die "SPEEDTEST truncate failed"; $t0 = [gettimeofday]; testins3($dbh, $data); $elapsed = tv_interval($t0, [gettimeofday]); say "3 Elapsed: $elapsed sec " . rowcnt($dbh) . " rows"; $dbh->do('truncate table speedtest') or die "SPEEDTEST truncate failed"; #$dbh->{ora_verbose} = 6; #$dbh->{ora_oci_success_warn} = 1; $t0 = [gettimeofday]; testins4($dbh, $data); $elapsed = tv_interval($t0, [gettimeofday]); say "4 Elapsed: $elapsed sec " . rowcnt($dbh) . " rows"; $dbh->disconnect; exit 0; __END__ #### // // g++ -std=c++11 -Wall -g speedtest.cpp -I/usr/local/include // -I ${ORACLE_HOME}/rdbms/public -L ${ORACLE_HOME}/lib -lclntsh // -o speedtest && ./speedtest // #include #include #include #include #include #include #define OTL_ORA12C #define OTL_STL #define OTL_EXCEPTION_STM_TEXT_SIZE 32767 #define OTL_ORA_UTF8 #if 0 #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define OTL_TRACE_LEVEL 0xff #define OTL_TRACE_STREAM cerr #define OTL_TRACE_LINE_PREFIX "MY OTL TRACE " __FILE__ ":" TOSTRING(__LINE__) " ==> " #endif using namespace std; #include // include the OTL 4.0 header file class data { public: data(size_t nrows = 1) : c_numrows(nrows), c_strlen(8) { genint(id); genstr(name); gendate(aod); gencurr(curr1); gendouble(price1); gencurr(curr2); gendouble(price2); } void print(void); string pdate(struct tm); size_t c_numrows; vector id; vector name; vector aod; vector curr1; vector price1; vector curr2; vector price2; private: size_t c_strlen; void gencurr(vector &); void genstr(vector &); void genint(vector &); void gendouble(vector &); void gendate(vector &); }; void data::print(void) { cout << "Num of rows: " << c_numrows << '\n'; for(size_t n=0; n & cvec) { for(size_t n=0; n & vstr) { for(size_t n=0; n & vint) { for(size_t n=0; n & vdouble) { for(size_t n=0; n & vtm) { for(size_t n=0; n, :name, :aod, :curr1, :price1, :curr2, :price2)", db // connect object ); for(size_t i=0; i= 2 )? argv[1] : "") << endl; //------------------------------------------------ data d(argc >= 2 ? atoi(argv[1]) : 1); //d.print(); //------------------------------------------------ int i = argc >= 3 ? atoi(argv[2])-1 : 0; cout << setw(8) << i+1 << " " << setw(10) << d.id[i] << " - " << d.name[i] << " - " << d.pdate(d.aod[i]) << " - " << d.curr1[i] << " - " << setw(10) << d.price1[i] << " - " << d.curr2[i] << " - " << setw(10) << d.price2[i] << endl; //------------------------------------------------ otl_connect db; // connect object otl_connect::otl_initialize(); // initialize OCI environment try { db.rlogon("???/???@???"); // connect to Oracle long rpc; rpc = otl_cursor::direct_exec(db, "alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'"); cout << "Alter session : " << rpc << endl; rpc = otl_cursor::direct_exec(db, "truncate table speedtest"); cout << "Speedtest truncated : " << rpc << endl; time_t t1 = time(NULL); insert(db, d); time_t t2 = time(NULL); cout << "Runtime: " << t2 - t1 << endl; db.commit(); } catch(otl_exception& p) { // intercept OTL exceptions cerr << p.msg <