请考虑包含大约 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 |
+-------+-------------------------------+--------+
n
中的主键,具有 BTREE 类型。
任务是更新下表中的字段 cdf;
> SELECT * from n_cdf_temp;
+-------+--------+
| n | cdf |
+-------+--------+
| 10002 | 16 |
+-------+--------+
n
中的主键,具有 BTREE 类型。
尽管计划移至 int
类型,但两个 n
字段仍具有 char(9)
类型。
作为示例,该表只有一条记录,但也应该有几百万行。
我尝试的命令是,按以下顺序:
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 条记录时,查询耗时约 1000 条。 18分钟。 MySQL 版本 5.0.67,旧版 Linux box P4,1GB RAM。
我还应该做什么才能在可接受的时间内大幅提高 UPDATE 性能?
查询 3 的 SELECT 版本的预计到达时间解释:
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) –
最佳答案
从您发布的说明来看,它似乎拒绝使用“y”表上的索引。在 EXPLAIN 的第 2 行中,注意'key: NULL key_len: NULL'。是否有可能两个表的主键数据类型不同?
关于mysql - 从只有一条记录的表更新太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5418737/