我必须在mysql数据库中更新2M*2行。
所有的信息都在一个文件中,我用php处理这个文件。我获取数组中的信息,然后将其推送到数据库中
UPDATE processed
SET number1=$row[1], number2=$row[2], timestamp=unix_timestamp()
where match (id) against ('\"$id\"' IN BOOLEAN MODE) limit 1这是有效的-但它需要这么长的时间...
我在(id)上有一个索引(主)。
我尝试使用全文索引上的(id)以外的东西(我使用的是Myisam) -它甚至更慢。
由于我的数据库非常大,并且mysql必须遍历所有内容才能找到要更新的正确行,所以每次更新都需要几秒钟的时间。这意味着需要几天的时间来处理我的更新!
有没有更快的方法来做到这一点?如果我切换到innodb,会不会更快?(即使不是这样,我想在更新期间也会很酷,我的整个表都不会被锁定)。
由于number1和number2都是数字,我想将所有必须更新为相同数字的(id)分组-这样会更快吗?
有没有办法调优mysqld,让number1、number2和id列留在内存中,让它更快地访问/更新?
任何想法都是受欢迎的,因为我完全迷失了。:)
编辑:添加示例代码,以便您了解我的情况:
foreach ($data_rows as $rows) {
$row=explode(":", $rows); // $row[0] info
// $row[1] new number1
// $row[2] new number2
$query = $db->query("select * from processed where match (info) against ('\"$info\"' IN BOOLEAN MODE) limit 1");
while ($line = $query->fetch_object())
{
$data[$line->hash]['number1']=$line->number1;
$data[$line->hash]['number2']=$line->number2;
$id=$line->id;
}
if (is_array($data[$info])) { // Check if we have this one in the database.
// If the number is correct, no need to update.
if (($data[$info]['number1'] != $row[1]) && ($data[$info]['number2'] != $row[2])) {
$db->query("UPDATE processed SET number1=$row[1], number2=$row[2], timestamp=unix_timestamp() where id=$id");
print "updated - $info - $row[1] - $row[2]\n";
}
}
else {
print "$info not in database\n";
}
} shema:
CREATE TABLE `processed` (
`id` int(30) NOT NULL AUTO_INCREMENT,
`timestamp` int(14) DEFAULT NULL,
`name` text,
`category` int(2) DEFAULT '0',
`subcat` int(2) DEFAULT '0',
`number1` int(20) NOT NULL,
`number2` int(20) NOT NULL,
`comment` text,
`hash` text,
`url` text,
PRIMARY KEY (`id`),
FULLTEXT KEY `name` (`name`),
FULLTEXT KEY `hash` (`hash`)
) ENGINE=MyISAM AUTO_INCREMENT=1328365 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;再次编辑:
在改善我的UPDATEs时间方面,ANALYZE TABLE processed;确实有很大的帮助。(新的索引!)
仍然会将我的数据添加到另一个表中并连接更新:)
发布于 2011-09-14 00:26:42
您正在执行2M*2个UPDATE命令。这确实需要一段时间。
我建议您将文件内容转储到一个临时表中,然后运行一个UPDATE命令。
更新
下面是如何运行单个连接的UPDATE
UPDATE processed
inner join DumpTable on processed.id = DumpTable.id
SET number1=DumpTable.value1 , number2=DumpTable.value2, timestamp=unix_timestamp()发布于 2011-09-14 00:28:11
好的,a)你应该经常清理你的数据-
sprintf("UPDATE processed
SET number1=%d, number2=%d, timestamp=unix_timestamp()
WHERE match (id)
AGAINST ('%d' $id IN BOOLEAN MODE) limit 1",
mysql_real_escape_string($row[1]),
mysql_real_escape_string($row[2]),
mysql_real_escape_string($id)
);此外,如果您切换到InnoDB,它可能会稍微快一点,然而,对于许多人来说,这是一个更好的选择,因为您不会在每次更新时锁定正在处理的整个表,您只会锁定正在更新的行。
因此,这是最值得考虑的事情,请阅读以下链接:http://www.kavoir.com/2009/09/mysql-engines-innodb-vs-myisam-a-comparison-of-pros-and-cons.html
发布于 2011-09-14 00:30:57
看一看:
http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html
750,000 bit可能会让事情变得更快一些。
https://stackoverflow.com/questions/7405188
复制相似问题