我必须在mysql数据库中更新2M * 2rows。
所有信息都在一个文件中,我用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会更快吗? (即使它不是我想在更新期间它可能很酷,我的整个表格都不会被锁定)。
作为数字1& number2是数字,我虽然将所有必须更新的(id)分组到相同的数字 - 会更快吗?
有没有办法调整mysqld以便number1,number2& id colums会留在RAM中,使访问/更新更快吗?
任何想法都是受欢迎的,因为我完全迷失了...... :)
编辑:添加示例代码,以便您了解我的情况:
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";
}
}
玛:
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 */;
再次编辑:
ANALYZE TABLE processed;
在改善UPDATEs
的时间方面做了很多帮助。 (新指数!)
将我的数据添加到另一个表格中无论如何加入更新:)
答案 0 :(得分:1)
您正在执行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()
答案 1 :(得分:0)
那么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它可能会稍微快一点,但是,对于很多人来说这是一个更好的选择,因为你没有锁定你正在为每个UPDATE工作的整个表,你只能锁定行你正在更新。
因此,最需要考虑的是,请阅读以下链接:http://www.kavoir.com/2009/09/mysql-engines-innodb-vs-myisam-a-comparison-of-pros-and-cons.html
答案 2 :(得分:0)
看看:
http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html
750,000qps可能会加快速度。