e2ka has asked for the wisdom of the Perl Monks concerning the following question:
O wise and merciful Monks, please consider the first question from a fool such as I,
I am writing a database which will contain time variable information which can be queried by its Interval of Validity, (IoV). This is merely a time duration given by its DATETIME since and DATETIME till. The rule is that you cannot insert an IoV that overlaps with IoV's already in the database. The other rule is that the insertions should be as fast as possible. To satisfy the first rule, a check must be made for overlaps before every insertion attempt.
I am finding that performing this check is decreasing my performance exponentially. I seem to have narrowed it down to a problem or misunderstanding of the perl DBI, as I wrote a test case in the vile tongue Java and there was no decrease in performance.
Here is the idea behind my test case:
connect to database and recreate tables insert 10000 rows into the parent table (channelView) prepare the statements for checking for overlaps and inserting to the data table (COND_dummy) for 10000 insertions { make a new iov check that the iov does not overlap insert the iov and some data if we have inserted 100 things, commit a transaction if we have inserted 1000 things, report performance }
Here are the results of the test case on my setup (Perl 5.8, MySQL 4.1, newest DBI and DBD::myqsl, fast machine...). On the right column you see the number of inserts per second.
Connect to database...Done. Reset database...Done. Define the database...Done. Fill channelView...Done. Begin insertions... [#insert] [date time] [ins/s] 1000 2005-03-08 12:38:25 808.696 2000 2005-03-08 12:38:27 482.931 3000 2005-03-08 12:38:30 329.941 4000 2005-03-08 12:38:34 255.688 5000 2005-03-08 12:38:39 209.914 6000 2005-03-08 12:38:45 169.025 7000 2005-03-08 12:38:51 153.192 8000 2005-03-08 12:38:59 133.599 9000 2005-03-08 12:39:07 120.618 10000 2005-03-08 12:39:16 109.312
What follows is my perl test case, which does exactly the same as a Java test case, and has (quickly) decreasing performance.
#!/usr/bin/perl + use warnings; use strict; $|++; + + use DBI; use POSIX; use Time::HiRes qw/gettimeofday/; use Data::Dumper; + my $db = "test_condDb_perform"; my $cond_name = "COND_dummy"; + print "Connect to database..."; my $dbh = DBI->connect("DBI:mysql:host=localhost;db=$db", "", "", {RaiseError=>1, AutoCommit=>1}); print "Done.\n"; + # reset the DB print "Reset database..."; $dbh->do( qq[ DROP DATABASE $db ] ); $dbh->do( qq[ CREATE DATABASE $db ]); $dbh->do( qq[ USE $db ]); print "Done.\n"; + + # define the database print "Define the database..."; $dbh->begin_work(); my $sql; $sql = qq[ CREATE TABLE channelView ( logic_id INT PRIMARY KEY ) TYPE=InnoDB ]; + $dbh->do($sql); + $sql = qq[ CREATE TABLE $cond_name ( logic_id INT, since DATETIME, till DATETIME, value FLOAT, PRIMARY KEY (logic_id, since, til +l), INDEX IoV (since, till), FOREIGN KEY (logic_id) REFERENCES channelView (logic_id) ) TYPE=InnoDB ]; $dbh->do($sql); $dbh->commit(); print "Done.\n"; + + # fill up the channelView print "Fill channelView..."; $dbh->begin_work(); $sql = qq[ INSERT INTO channelView SET logic_id = ? ]; my $fill_chview_h = $dbh->prepare_cached($sql); for (1..10000) { $fill_chview_h->execute($_); } $dbh->commit(); print "Done.\n"; # insert and write performance print "Begin insertions...\n\n"; my $iov_seed = time; my $logic_id = 9999; + my $count=0; my $MAXCOUNT = 1000; my $total=0; my $start = gettimeofday; my $commit_cnt = 0; my $commit_size = 100; + $sql = qq[ SELECT logic_id, since, till FROM $cond_name WHERE logic_id = ? AND ((since >= ? AND since < ?) OR (till > ? AND till < ?) OR (? >= since AND ? < till)) LIMIT 1 ]; my $overlap_check_h = $dbh->prepare_cached($sql); + $sql = qq[INSERT INTO $cond_name SET logic_id = ?, since = ?, till = ?, value = ?]; my $insert_h = $dbh->prepare_cached($sql); + $dbh->begin_work(); for (0..10000) { my ($t1, $t2) = make_iov(); $overlap_check_h->execute($logic_id, $t1, $t2, $t1, $t2, $t1, $t2); my @overlap = $overlap_check_h->fetchrow_array(); if (@overlap) { print "OVERLAP! That's impossible!\n"; } else { $insert_h->execute($logic_id, $t1, $t2, 1); $count++; $commit_cnt++; if ($commit_cnt == $commit_size) { $dbh->commit(); $dbh->begin_work(); $commit_cnt = 0; } if ($count == $MAXCOUNT) { report(); } } } $dbh->commit(); + sub report { printf "%9s %19s %9s\n", "[#insert]", "[date time]", "[ins/s]" if $total == 0; my $now = gettimeofday; $total += $count; printf "%9d %s %9.3f\n", $total, strftime("%Y-%m-%d %H:%M:%S", localtime), $count/(($now - $start)); $count = 0; $start = $now; } sub make_iov { return ( strftime("%Y-%m-%d %H:%M:%S", localtime($iov_seed) ), strftime("%Y-%m-%d %H:%M:%S", localtime(++$iov_seed) ) ); }
What is the cause of this horrible decrease in performance? Please, share your wisdom.
-e2ka
Edit by BazB - added readmore tags
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: DBI performance problem with MySQL
by dragonchild (Archbishop) on Mar 08, 2005 at 20:03 UTC | |
by e2ka (Acolyte) on Mar 08, 2005 at 22:12 UTC | |
by dragonchild (Archbishop) on Mar 09, 2005 at 03:08 UTC | |
by e2ka (Acolyte) on Mar 09, 2005 at 17:03 UTC | |
by dragonchild (Archbishop) on Mar 09, 2005 at 19:03 UTC | |
| |
by mshiltonj (Sexton) on Mar 10, 2005 at 14:33 UTC | |
|
Re: DBI performance problem with MySQL
by RazorbladeBidet (Friar) on Mar 08, 2005 at 19:45 UTC |