-1

我目前正在从事一个涉及 MySQL 数据库数据操作的项目。首先,我需要告诉您,我使用的是在同一台机器上执行的 perl 脚本。另外,我想说一下我正在处理的表: 创建表如下:

CREATE TABLE `deCoupled` (
    `AA` double NOT NULL DEFAULT '0',
     ...several other fields,
     KEY `AA` (`AA`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

为了优化我处理数据的方式,我创建了一个临时表,如下所示:

CREATE TABLE `temp_deCoupled` AS SELECT * FROM `deCoupled` ORDER BY field1,field2,...,fieldN

并添加数据操作所需的 auto_increment 键字段:

ALTER TABLE `temp_deCoupled` ADD COLUMN MY_KEY INT NOT NULL AUTO_INCREMENT KEY
ALTER TABLE `temp_deCoupled` ADD INDEX (MY_KEY)

我像这样更改表,因为我使用查询扫描表

SELECT COUNT(`AA`), field1, field2,..., fieldN FROM `temp_deCoupled`
GROUP BY field1, field2,..., fieldN ORDER BY field1, field2,..., fieldN

我根据 MY_KEY 字段对记录执行更新。不幸的是,对于大约 75000 条记录的记录,在具有双核 CPU 和 2gigs 内存的 pc 上大约需要 75 分钟。另外,我需要告诉您,操纵数据的 perl 脚本不会进行任何复杂的计算。

我尝试调整 MYSQL 服务器,并使用以下内容更新了 my.cnf 文件:

key_buffer = 256M
sort_buffer_size = 128M
read_buffer_size = 64M
read_rnd_buffer_size = 64M
key_buffer_size = 128M
table_cache = 1024
query_cache_limit = 128M
query_cache_size = 128M
innodb_buffer_pool_size = 768M
innodb_thread_concurrency = 8
innodb_flush_method = o_DIRECT

我真的需要降低脚本的执行时间。任何人都可以提出任何建议吗?

为了更准确地了解更新,我将发布以下代码示例:

$qSel = "SELECT COUNT(*), field1,..., fieldN FROM `temp_deCoupled` GROUP BY field1,..., fieldN ORDER BY field1,...,fieldN";
$stmt = $dbh->prepare($qSel);
$stmt->execute() or die "Error occurred: $DBI::errstr.\n";
while($stmt->fetch()) {
    .... *some code*...
    $q_sel_keys = "SELECT MY_KEY FROM `temp_deCoupled` WHERE field1 = value1 AND ... AND fieldN = valueN";
    $stmt1 = $dbh->prepare($q_sel_keys);
    $stmt1->execute() or die "Error occured: $DBI::errstr.\n";
    ...*some other code*...
    $q_Update_Records = "UPDATE `temp_deCoupled` SET field1=val_1,..., fieldN=val_N WHERE MY_KEY = key1 OR MY_KEY = key2 OR ... OR MY_KEY = keyN";
    $stmt1 = $dbh->prepare($q_Update_Records);
    $tmp_c = $stmt1->execute() or die "Error occured: $DBI::errstr.\n";
    ...*some final code*...
}

这就是 Perl 中数据操作的主体(通常)。

4

3 回答 3

1

看起来您提供了很多信息,但没有提供所需的关键信息(如果您愿意原谅双关语)。那就是:需要这么长时间的更新有什么用?

如果您单独执行 75000 条更新语句,那将需要很长时间。尝试将它们组合在一起,其中更新执行的操作相同,只有键不同,例如:

update temp_deCoupled set fieldx=..., fieldy=... where my_key in (?,?,?,?,...)

在最坏的情况下,更新在很大程度上是不同的,您可以使用另一个表来提供更新所需的信息。例如,给定这张表:

create table foo ( id int primary key, bar double );

您需要根据 id 将每个条乘以不同的值,创建另一个表来保存乘数,将它们插入脚本的单个请求中,然后更新:

create temporary table foo_multiply ( id int primary key, mult double );
insert into foo_multiply values (1,123),(2,42),(3,666),...;
update foo inner join foo_multiply using (id) set foo.bar=foo.bar * foo_multiply.mult;

将插入语句分成不超过 1MB 左右的行可能是个好主意。在极端情况下,将要插入的数据写入文件并使用“LOAD DATA INFILE”加载它。

于 2012-08-27T23:09:50.300 回答
0

通过将 temp_deCoupled 表创建为:

CREATE TABLE `temp_deCoupled` ENGINE = MEMORY AS SELECT * FROM `deCoupled` ORDER BY field1,field2,...,fieldN

我还在my.cnf上做了以下配置:

max_heap_table_size = 512M

我要感谢大家对您表现出的兴趣。

于 2012-08-28T11:21:46.863 回答
0

默认情况下,MySQL 驱动程序在每个语句之后提交对数据库的更改。当进行大量更新时,这通常会导致性能不佳。

禁用 AutoCommit 模式可以解决您的性能问题。但与@ystsh 想法一样,这更多地基于您尚未提供的信息。

于 2012-08-28T11:42:00.857 回答