请考虑包含大约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) –
答案 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”的所有值的更新表?