MySQL-perl脚本的优化

MySQL-perl脚本的优化,mysql,perl,Mysql,Perl,我目前正在从事一个涉及MySQL数据库数据操作的项目。首先,我需要告诉您,我使用的是在同一台机器上执行的perl脚本。另外,我想说一些关于我正在处理的表的事情:create表如下所示: CREATE TABLE `deCoupled` ( `AA` double NOT NULL DEFAULT '0', ...several other fields, KEY `AA` (`AA`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 为

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

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
并添加数据操作所需的自动增量键字段:

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条记录,在一台pc上大约需要75分钟 具有双核CPU和2gigs ram。另外,我需要告诉您,操纵数据的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中数据操作的主体(通常)。

看起来您提供了很多信息,但没有提供所需的关键信息(如果您不介意使用双关语的话)。也就是说:需要这么长时间的更新会做什么

如果您单独执行75000条update语句,这将需要很长时间。 如果更新执行的操作相同,但密钥不同,请尝试将它们分组在一起,例如:

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;
最好将insert语句拆分成不超过1MB的行。
在极端情况下,将要插入的数据写入文件,并使用“加载数据填充”将其加载。

我已通过创建temp_解耦表将执行时间降低到12分钟,如下所示:

CREATE TABLE `temp_deCoupled` ENGINE = MEMORY AS SELECT * FROM `deCoupled` ORDER BY field1,field2,...,fieldN
我还在my.cnf上进行了以下配置:

max_heap_table_size = 512M

我要感谢大家对您的关注。

默认情况下,MySQL驱动程序会在每条语句后将更改提交到数据库。在进行大量更新时,这通常会导致性能不理想


禁用自动提交模式可以解决性能问题。但与@ystsh idea一样,这更多是基于您尚未提供的信息

在交替之前降低指数可能会加快速度。也许您还应该展示您的Perl代码,这样我们就可以看到您如何准确地对数据库执行操作。到目前为止,您所展示的任何内容都无法解释为什么要使用临时表,或者为什么要在创建临时表的select中使用“order by”。为什么要在原始表已经有键的情况下添加整数键?“但在评论之前,请仔细阅读“-任何好事都会受到惩罚。如果你不发布代码,我们就无法为你优化它。@popanik:如果表复制和重新索引不是问题,那么你告诉我们的所有相关信息就是你有一个表
temp\u deCoupled
,带有一个自动递增键,对它执行一系列未公开的操作需要很长时间。我们该怎么帮你呢?谢谢你的回答。正如我前面提到的,更新是稀疏的,并且取决于MY_KEY字段。你对更新进行分组的建议是我没有想到的,我会尝试一下,看看它是如何工作的。另外@ysth,你认为我在我的帖子中所做的更改是足够的,还是我应该做些其他事情?我用更多的信息更新了最初的帖子。请,如果你有时间,去看看。再次感谢:)在第一篇文章中,我从perl脚本中添加了一些与数据操作相关的更多信息。我不认为任何更多的信息会与mysql服务器的性能相关。当然这完全取决于您,但您没有提供任何与每连接配置相关的信息。每个连接最相关的设置是启用自动提交,但其他属性也可能会对性能产生影响。如果保证数据适合内存,那么最好将数据全部读取到一个大哈希中,并在perl中修改,然后将其全部插入一个新表中。