hotti: Insert mit Rückgabe der ID

Beitrag lesen

hi Tom,

Hast Du es schon mit REPLACE und "On DUPLICATE KEY UPDATE" ausprobiert?

Proprietär und unperformant ;)

Überraschung:
Benchmark: timing 100000000 iterations of New Way, Old Way...
   New Way:  1 wallclock secs ( 0.30 usr +  0.00 sys =  0.30 CPU) @ 336700336.70/s (n=100000000)
            (warning: too few iterations for a reliable count)
   Old Way:  2 wallclock secs ( 1.77 usr +  0.00 sys =  1.77 CPU) @ 56657223.80/s (n=100000000)
               Rate Old Way New Way
Old Way  56657224/s      --    -83%
New Way 336700337/s    494%      --

Viele Grüße,
Horst ;)

PS: Perl-Code zum Nachvollziehen:

  
  
use strict;  
use warnings;  
use DBI;  
use Data::Dumper;  
use Benchmark qw(cmpthese);  
  
my $DBH = dbh() or die $@;  
  
  
#create('user') || drop('user');  
  
# Statements  
my $STH_IGNORE = $DBH->prepare("INSERT IGNORE INTO user(user_id, user_name)VALUES(?,?)");  
my $STH_INSERT = $DBH->prepare("INSERT INTO user(user_id, user_name)VALUES(?,?)");  
my $STH_TEST   = $DBH->prepare("SELECT id FROM user WHERE user_id=? AND user_name=?");  
  
my $user_id = 'hh10';  
my $user_name = 'Horst Haselhuhn';  
my $id = undef;  
  
#my $id = insert_ignore({user_id => $user_id, user_name => 'Horst Haselhuhn'}) or die $@;  
#print "Old Way: $id\n";  
  
#$id = insert({user_id => $user_id, user_name => $user_name}) or die $@;  
#print "New Way: $id\n";  
  
# Jetzt machen wir mal ein Benchmark  
cmpthese(100000000, {  
        'Old Way' => insert({user_id => $user_id, user_name => $user_name}),  
        'New Way' => insert_ignore({user_id => $user_id, user_name => $user_name}) ,  
});  
  
  
# Herkömmlicher Weg  
sub insert{  
	my $r = shift;  
	my @args = ($r->{user_id}, $r->{user_name});  
	my $id = '0E0';  
	eval{  
		$STH_TEST->execute(@args);  
		my $id_ist = $STH_TEST->fetchrow_array;  
		if($id_ist){  
			#print "DRIN: $id_ist\n";  
			$id = $id_ist;  
		}  
		else{  
			$STH_INSERT->execute(@args);  
			$id = $DBH->selectrow_array("SELECT LAST_INSERT_ID()");  
		}  
	};  
	return $@ ? undef : $id;	  
}  
  
  
# Neuer Weg mit INSERT IGNORE  
sub insert_ignore{  
	my $r = shift;  
	my @args = ($r->{user_id}, $r->{user_name});  
	my $id = '0E0';  
	eval{  
		my $rv = $STH_IGNORE->execute(@args); # IGNORE => 0E0, NEU => 1  
		if($rv == 0){  
			# 0E0, kein Fehler, Record schon drin  
			$id = $DBH->selectrow_array("SELECT id FROM user WHERE user_id=? AND user_name=?", {}, @args);  
			#print "Drin: $id\n";  
		}  
		else{  
			$id = $DBH->selectrow_array("SELECT LAST_INSERT_ID()");  
			#print "Neu: $id\n";  
		}  
	};  
	return $@ ? undef : $id;	  
}  
  
sub drop{  
	my $table_name = shift;  
	eval{ $DBH->do("DROP TABLE $table_name"); };  
	print "DROP\n";  
	return $@ ? undef : 1;  
}  
sub create{  
	my $table_name = shift;  
	my %qq = creates();  
	my $qtable = $qq{$table_name};  
	eval{ $DBH->do($qtable) };  
	print "CREATE\n";  
	return $@ ? undef : 1;  
}  
  
  
sub creates{  
	return (  
		user => q(  
			CREATE TABLE user(  
				id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,  
				user_name VARCHAR(50) NOT NULL DEFAULT '',  
				user_id VARCHAR(50) NOT NULL DEFAULT '',  
				PRIMARY KEY (id),  
				UNIQUE KEY ident(user_name, user_id)  
			)DEFAULT CHARSET=UTF8  
		),  
	);  
}  
###########################################################################  
sub dbh{  
	my %cfg = (  
		base => 'myweb',  
		host => 'localhost',  
		port => 3306,  
		user => '',  
		pass => '',  
  
	@_);  
	my $dbh = undef;  
	eval{  
		$dbh = DBI->connect("DBI:mysql:$cfg{base}:$cfg{host}:$cfg{port}", $cfg{user}, $cfg{pass},  
			{RaiseError => 1, PrintError => 0}  
		);  
	};  
	return $@ ? undef : $dbh;  
}