从一个记录的表更新太慢

时间:2011-03-24 11:59:03

标签: mysql

请考虑包含大约1900万条记录的表bd.nn:

> SELECT n, name, cdf from bd.nn limit 4;
+-------+-------------------------------+--------+
| n     | name                          | cdf    |
+-------+-------------------------------+--------+
| 10002 | JOJE                          | NULL   |
| 10010 | AUGUSTINA                     | NULL   |
| 10029 | CARDOS                        | NULL   |
| 10037 | DE FRITOS                     | NULL   |
+-------+-------------------------------+--------+

具有BTREE类型的n中的主键。

任务是从下表中更新字段cdf;

> SELECT * from n_cdf_temp;
+-------+--------+
| n     | cdf    |
+-------+--------+
| 10002 | 16     |
+-------+--------+

具有BTREE类型的n中的主键。 这两个n字段仍然有char(9)类型,但计划移至int类型。

此表只有一条记录作为示例,但也应该有几百万行。

我尝试的命令是按此顺序:

UPDATE bd.nn y SET cdf = (SELECT cdf from temp.n_cdf_temp t WHERE t.n = y.n);

UPDATE bd.nn y SET cdf = (SELECT cdf from temp.n_cdf_temp t WHERE t.n = y.n) WHERE y.n in (SELECT n from temp.n_cdf_temp WHERE cdf IS NOT NULL);

UPDATE bd.nn y INNER JOIN temp.n_cdf_temp t ON y.n=t.n SET y.cdf = t.cdf;

UPDATE bd.nn y FORCE KEY (PRIMARY) INNER JOIN temp.n_cdf_temp t ON y.n=t.n SET y.cdf = t.cdf;

问题是此更新需要很长时间。 在我的带有MyISAM表的开发笔记本电脑(Core 2 Duo)中,第四个命令的更新耗时6.5秒,第三个命令的更新耗时约30秒。 如果n_cdf_temp有1000条记录,那么MyISAM引擎需要45秒。

但是在生产服务器中,使用InnoDB表,当n_cdf_temp只有一条记录时,更新花了14分钟。 当n_cdf_temp有1000条记录时,查询占用了大约1。 18分钟。 旧版Linux机箱中的MySQL版本5.0.67,1GB RAM。

我还应该做些什么才能在可接受的时间内大大提高UPDATE性能?

ETA EXPLAIN for SELECT版本的查询3:

EXPLAIN SELECT y.n, t.cdf from bd.nn y INNER JOIN temp.n_cdf_temp t ON y.n=t.n\G 
** 1. row id: 1 select_type: SIMPLE table: t type: index possible_keys: PRIMARY key: cdf key_len: 2 ref: NULL rows: 1 Extra: Using index 
** 2. row id: 1 select_type: SIMPLE table: y type: ALL possible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 18744700 Extra: Range checked for each record (index map: 0x1) –

2 个答案:

答案 0 :(得分:1)

在您发布的EXPLAIN中,似乎拒绝使用“y”表上的索引。在EXPLAIN的第2行中,注意'key:NULL key_len:NULL'。是否有可能两个表的主键的数据类型不同?

答案 1 :(得分:0)

解决此问题的一种方法是:发出2个请求。

一个是: 从n_cdf_temp中选择cdf WHERE n ='X';

第二: UPDATE bd.nn y SET cdf ='第一次请求的结果'WHERE n ='X';

当然,这种方法并不理想,但它非常简单且有效。

或者您想要“X”的所有值的更新表?