我有一个哈希,其中包含所有计算用户'考试成绩(系统用户是我的学生),其中user_id
是哈希的关键,等级是相应的值。这个哈希有超过50,000个元素。我想用这些计算的等级更新数据库。
my %grade_of = compute_grades_hash( ... ); # Some logic to compute grades
my $dbh = DBI->connect( ... ) or die( ... ); # DBI parameters are hidden in this sample
my $sql = "UPDATE User SET grade = ? WHERE id = ?";
my $sth = $dbh->prepare($sql);
foreach my $user_id ( keys %grade_of ) {
$sth->execute( $grade_of{$user_id}, $user_id );
}
但是,如果我是对的,这会导致执行超过50,000个查询,这意味着超过50,000次访问数据库(如果我假设错误,请在此声明中随意纠正我。)
my %grade_of = compute_grades_hash( ... ); # Some logic to compute grades
my $dbh = DBI->connect( ... ) or die( ... ); # DBI parameters are hidden in this sample
my $sql = build_query ( \%grade_of );
my $sth = $dbh->prepare($sql);
$sth->execute();
sub build_query {
# Builds a string in the followig form:
# UPDATE User
# SET grade = (case when user_id = 10 then 96
# when user_id = 14 then 92
# when user_id = 26 then 85
# ...
# end)
# So it generates a very long query-string for the 50000 records
...
return $sql_query;
}
以下是我的问题:
这是该案件的正确解决方案吗?
很长的SQL语句会影响查询性能吗?
Perl DBI和/或MySQL中的查询长度是否有任何限制?
还有更优雅的解决方案吗?我错过了内置功能 我可以使用它吗?
顺便说一下,如果答案取决于以下信息,以下是我的完整性系统规范:
$ mysql --version mysql Ver 14.14 Distrib 5.6.25, for Linux (x86_64) $ perldoc -m DBI | grep -m1 VERSION $VERSION = "1.621"; $ perl --version This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux
答案 0 :(得分:5)
您是否尝试过运行其中任何一种?
你的第一次尝试是正确的。这就是为数据库制作的那种东西。你的第二个版本可能要慢得多。根据SQL引擎的优化方式,但无论您如何制定SQL,您的数据库仍然必须进行50,000次更新。你的第二次尝试迫使它做更多的工作来决定那些更新是什么
您可以使用交易
来加快流程,并避免某些记录更新而其他记录无法更新的可能性在开始更新数据库之前,请致电
$dbh->begin_work
当它们全部完成时,你需要
$dbh->commit
这将创建一个对表进行更改的列表,并在调用commit
方法时 make 这些更改
无论如何,您应该使用测试数据库,因此我建议您设置一个包含可管理数量的数据,以便快速提供结果。然后你可以尝试你的两个选项,以及你想到的任何选项,并确定他们的行为方式
答案 1 :(得分:1)
这可能会更快:
CREATE TEMPORARY TABLE `Updates` (
`user_id` ... NOT NULL,
`grade` ... NOT NULL
);
INSERT INTO `Updates` VALUES
( ..., ... ),
( ..., ... ),
...;
ALTER TABLE `Updates` ADD UNIQUE `user_id`;
UPDATE `User`
JOIN `Updates`
ON `User`.`user_id` = `Updates`.`user_id`
SET `User`.`grade` = `Updates`.`grade`;