My understanding is that Perl extracts the hash keys into a list in-memory when you use the keys operator (function?).
When I know I'll be working with large hashes like this, I tend to use each, so the key/value pairs are fetched from the hash one-at-a-time.
If you're using lots of memory, give this a try:
my $dbh=DBI->connect("xxxx"); # My DB is SQLSERVER 2005
my $sth=$dbh->prepare(qq{ UPDATE tab SET d=? WHERE id=?});
for (my ($key,$val) = each %hash) {
$sth->execute($hash{$key},$val);
}
$sth->finish;
$dbh->disconnect;